2011-11-09 19 views
14

variabili dei tipi di can be value-initialized like this incorporati:Come si inizializza il valore di un puntatore di tipo * usando la sintassi di Tipo()?

int var = int(); 

questo modo ottengo il valore predefinito di int senza hardcoding lo zero nel mio codice.

Tuttavia, se provo a fare roba simile per un puntatore:

int* ptr = int*(); 

il compilatore (Visual C++ 10) si rifiuta di compilare che (dice type int unexpected).

Come si inizializza il valore di un puntatore in modo simile?

+1

Buona domanda. Si ottiene anche un errore simile per 'unsigned int'. –

+1

Ora la domanda è perché vorresti farlo. Puoi inizializzare i puntatori con 0 direttamente (se sai che è un puntatore), e se questo è nascosto in qualche template, allora 'T()' funzionerà bene ... Non capisco come questa domanda abbia 11 upvotes:) –

risposta

4

Come faccio a valore-inizializzare un tipo * puntatore utilizzando il tipo() - come la sintassi?

Non è possibile. La sintassi T() è definita in 5.2.3/1.2 (C++ 03, una dicitura leggermente diversa in FDIS C++ 11). In particolare, il secondo paragrafo afferma:

L'espressione T(), dove T è uno specificatore di tipo semplice (7.1.5.2) per un tipo di oggetto completo senza matrice o il vuoto (eventualmente qualificato per cv) digita, crea un valore rval del tipo specificato, che è inizializzato a valore (8.5);

Ciò significa che int(), creerà un rvalue di tipo int e valore inizializzare esso. Ora il problema è che int* non è un identificatore di tipo semplice, ma piuttosto un identificatore di tipo elaborato. La definizione di semplice tipo-specificatore nella grammatica è:

simple-type-specifier: 
    ::opt nested-name-specifieropt type-name 
    ::opt nested-name-specifier template template-id 
    char 
    wchar_t 
    bool 
    short 
    int 
    long 
    signed 
    unsigned 
    float 
    double 
    void 

Con nome-tipo essendo definita come:

type-name: 
    class-name 
    enum-name 
    typedef-name 

Questo è ciò che rende il lavoro proposto soluzioni. La creazione del typedef (direttamente o tramite il modello) crea un nome tipo (terzo tipo) che può essere utilizzato come identificatore del tipo semplice (primo tipo).

1

Basta fare

int* x = int(); 

Assegna ancora 0 al puntatore rendendo puntare all'indirizzo NULL visto che sei inadempiente con il valore di default di int che è 0 in ogni caso.

In realtà, tutto funziona bene per tutti i tipi:

double* y = int(); 

L'indirizzo è ancora un 32 bit (o 64 bit a seconda della piattaforma) integer quindi penso che dovrebbe funzionare bene per tutti i tipi se si do = int().

+0

Wow, sembra una grave violazione del sistema dei tipi ed è incredibilmente interessante. Tuttavia non funzionerà per 'double *'. – sharptooth

+0

huh, interessante :) Dovrò verificarlo. Avrei pensato che avrebbe funzionato per tutti i tipi di puntatori. –

+0

Penso che funzioni bene, controlla la mia modifica. –

1

Ecco un modo:

template <typename T> 
T make_default() 
{ 
    return T(); 
} 

int main() 
{ 
    int *p = make_default<int*>(); 
} 
+0

Questo è un modo per creare un puntatore NULL. – DanDan

9

Utilizzare un typedef per fare un nome per il tipo di puntatore:

typedef int *ip; 

ip ptr = ip(); 

La stessa idea dovrebbe funzionare per altri tipi che richiedono più di un elemento lessicale (parola) per definire il nome del tipo (ad esempio, unsigned long, long long, unsigned long long *, ecc.).

+0

+1: più facile del mio ... –

+0

Sono confuso, un puntatore tiene semplicemente l'indirizzo in memoria della variabile - non dovrebbe essere solo int * x = int(), rendendo x hold 0 che è lo stesso di NULL? Immagino che mi manchi qualcosa dato che la gente continua a saltare oltre il mio, ahah, non capisco cosa sia. –

+0

@ w00te: Il tuo avrà lo stesso effetto, perché 0 è definito per la conversione in un puntatore nullo. Allo stesso tempo, sta chiedendo specificatamente come eseguire l'inizializzazione del valore, e tu non lo * lo faccia ("inizializzazione del valore" ha uno specifico significato definito nello standard C++ che è leggermente diverso dall'idea generale di inizializzando con un valore). –

-1

Questo è il modo in cui lo fai int * ptr = new int;

Heap pointers

+2

Questo valore non inizializza il puntatore. –

0

La ragione che non funziona è perché i puntatori non hanno costruttori.

La sintassi

int()

chiamate (in teoria)

int::int()

che inizializza la variabile. (Più probabilmente, il compilatore azzera appena la variabile, ma è perché "sa" di ints).

in C++ 11, è possibile utilizzare nullptr

int *ptr = nullptr;

In caso contrario, è praticamente necessario utilizzare NULL:

int *ptr = NULL;

+0

Ovviamente i puntatori hanno costruttori allo stesso modo 'int' ha - è tutto incorporato, dopo tutto. Posso dire 'T()' se 'T' è' typedef int * T', e non posso neanche usare '= unsigned int()'. È il solo problema puramente sintattico di ciò che non funziona con i nomi dei tipi composti. – sbi

3

Non richiede l'uso di typedef (ma esclusivo di C++ 11), che può essere utile quando si tratta di diversi tipi di puntatore:

template<typename T> 
using alias = T; 

poi alias<int*> è int*, in modo da poter fare int* p = alias<int*>().

Una soluzione analoga a disposizione C++ 03, utilizzando un metafunction identità:

template<typename T> 
struct identity { 
    typedef T type; 
}; 

int* p = identity<int*>::type(); 
+1

La versione C++ 03 richiede un typedef, è appena nascosto all'interno di un modello. La versione C++ 11 non crea un typedef, ma crea un nuovo tipo 'alias ' che diventa uno * identificatore del tipo semplice * e quindi incline alla * conversione del tipo esplicito * nella notazione * funzionale * –

+0

Perché non hai un 'puntatore ()'? ':' – sbi

+0

@sbi 'alias' ha altri usi. –

Problemi correlati