2010-01-27 4 views
8

La seguente riga di codice compila bene e si comporta:typedef e contenitori di puntatori const

list<const int *> int_pointers; // (1) 

Le due righe seguenti non lo fanno:

typedef int * IntPtr; 
list<const IntPtr> int_pointers; // (2) 

ottengo la stessa identica errori di compilazione per

Sono consapevole che l'ultima riga non è legale poiché gli elementi di un container STL devono essere assegnabile. Perché l'interprete del compilatore (2) è lo stesso di (3)?

risposta

9

Risposta breve:

  1. è una lista di puntatori a int costanti.
  2. è un elenco di puntatori costanti agli inte.
  3. è lo stesso 2.

const (e volatile) dovrebbe apparire naturalmente dopo il tipo si qualificano. Quando si scrive prima, il compilatore riscrive automaticamente internamente:

const int * 

diventa

int const * 

che è un puntatore a una costante int. Gli elenchi di questi verranno compilati correttamente poiché il puntatore stesso è ancora assegnabile.

8

Leggi le dichiarazioni di tipo C da destra a sinistra. Quindi "const int *" è un puntatore a ints costante ("const int" e "int const" significano la stessa cosa). Quelli sono perfettamente assegnabili. Ma (2) e (3) sono puntatori costanti di int, e quindi non assegnabili.

5

const IntPtr e const int* non sono la stessa cosa.

1) const int* è "puntatore a const int".

2) const IntPtr espande a int * const (si pensi (int *) const) che è "const puntatore int".

In breve, lo typedef si comporta come un insieme di parentesi. Non è possibile modificare const -ness di ciò a cui punta il puntatore d typedef.

3

const int * equivale a scrivere int const *, ovvero un valore costante puntato da un puntatore non costante.

Con typedef si definisce il puntatore stesso come costante, come nella terza frase.

5

Si sta chiedendo "Perché l'interpretazione del compilatore (2) è uguale a (3)?". Bene, perché in linguaggio C++ (così come in C) sono semanticamente uguale.Quando si definisce un typename come

typedef int *IntPtr; 

poi il tipo const IntPtr starà per int *const, non per const int *. È così che i nomi typedef funzionano in C++.

I nomi typedef in C++ non sono macro. Sebbene non definiscano nuovi tipi (solo alias per quelli esistenti), gli alias risultanti sono tuttavia "atomici", "monolitici" nel senso che tutti i qualificatori applicati all'alias verranno applicati come qualificatori di livello superiore. Quando si lavora con un nome typedef, non c'è modo di "intrufolarsi" in un qualificatore const in modo che possa "discendere" in una porzione di livello inferiore del tipo (int nel tuo caso).

Se ti ostini a usare typedef-nomi, non hai altra scelta immediata, ma di fornire due diversi typedef-nomi, come

typedef int *IntPtr; 
typedef const int *ConstIntPtr; 

e usare ConstIntPtr quando si ha bisogno di una versione puntatore a const di Il tipo.

+0

+1, buona risposta :-) –

0

Sono sicuro che sapete che const IntPtr e IntPtr const sono dello stesso tipo. Il che significa che lo list<const IntPtr> e lo list<IntPtr const> sono dello stesso tipo. Il che significa che stai provando a compilarlo:

typedef int * IntPtr; 
     list<IntPtr const> int_pointers; // (2bis)