2015-07-26 6 views
9

Sto leggendo C++ Primer e nella sezione 6.2 si dice: "inizializzazione parametro funziona allo stesso modo di inizializzazione variabile"Perché non posso fare foo ({"asd", "asd1"}) con foo (char * args [])?

Eppure, quando lo faccio:

void foo(char* args[]) {return;} 

int main() { 

char* args[]={"asd","dsa"}; // ok. 

foo({"asd","dsa"});   // error. 

} 

Perché?

+0

Cosa dice l'errore? –

+5

libri mentono. spesso per rendere le cose più semplici, a volte perché l'autore non sa meglio. –

+0

prova 'const char *' –

risposta

4

Come @ T.C. sottolineato nei commenti, gli argomenti nell'argomento funzione sono convertiti in un char ** perché le funzioni non possono prendere array come argomento. Dal momento che non è possibile fare

char **asd={"asd","dsa"}; 

il codice è illegale. La mia confusione deriva dal fatto che

char* args[]={"asd","dsa"}; 
char **asd=args; 

è legale.

+1

Lettura correlata: http://stackoverflow.com/questions/22677415/why-do-c-and-c-compilers-allow-array-lengths-in-function-signatures-when-they –

0

Perché è quello?

Prima di tutto in entrambi i casi, è necessario char const* perché si sta lavorando con stringhe letterali.

secondo luogo, {...} potrebbe funzionare se il tipo di parametro è un array, ma è char*[]regolato a char** (dovuto decayment) che non può essere inizializzato con un rinforzato-init-list.


alternativa utilizzare std::string e std::vector, come è già tempo di fare:

void foo(std::vector<std::string> args) {return;} 

e:

foo({"asd","dsa"}); 

sarà work just fine.

+0

Stai dicendo che '{...}' è dedotto a 'std :: initializer_list' quando non è mai il caso di inizializzare tipi non di classe (e non di dedurre da' auto'). E no, il tipo di parametro non è 'T []'. La dichiarazione è * regolata * in 'T *' e l'argomento (se un array) sarà convertito implicitamente. – 0x499602D2

+0

Sto usando Visual C++ 2010 e non include initializer_list. – Ant

0

"L'inizializzazione dei parametri funziona allo stesso modo dell'inizializzazione delle variabili."

Questo è vero per quanto riguarda la chiamata di costruttori, penso che significano. Tuttavia, gli inizializzatori sono speciali e diversi dalle espressioni di valore ordinario che è possibile assegnare a una variabile o passare a una chiamata di funzione.

C/C++ non ha un modo per scrivere un array anonimo letterale. Puoi solo farlo come inizializzatore mentre dichiari una variabile.

3

In genere è possibile sfruttare la nuova sintassi di inizializzazione e la semantica per utilizzare gli array anonimi come argomenti, ma è necessario passare attraverso alcuni cicli. Per esempio

typedef const char *CC2[2]; 

void foo(const CC2 &a) {} 

int main() { 
    foo({ "asd", "dsa" }); 
} 

Tuttavia, nel tuo caso questa tecnica non aiuterà perché si richiede una conversione serie-a-puntatore su un array temporaneo.Questo è illegale in C++.

typedef int A[2]; 

const A &r = A{ 1, 2 }; // reference binding is OK 
int *p = A{ 1, 2 };  // ERROR: taking address is not OK 

Quindi, se si vuole veramente fare qualcosa di simile, è possibile effettuare le seguenti operazioni

template <size_t N> void foo(const char *const (&args)[N]) {} 

int main() { 
    foo({ "asd", "dsa" }); 
} 

ma che non è esattamente quello che aveva in mente in origine.

Problemi correlati