2013-03-17 9 views
19

posso creare una variabile denominata con una serie come segue:Utilizzo dell'elenco di inizializzazione dell'array come temporaneo in C++ 11?

char s[] = {1, 2, 3, 0}; 
if (strcmp(s, t)) 
    ... 

Tuttavia, il seguente non funziona:

if (strcmp(char[]{1,2,3,0}, t)) 
    ... 

c'è qualche modo per specificare una matrice senza nome provvisorio con una lista di inizializzazione ? (In questo caso una stringa letterale avrebbe funzionato, ma per gli array diversi array char?)

Aggiornamento:

#include <iostream> 
#include <cstring> 

using namespace std; 

typedef char CA[]; 

int main() 
{ 
     cout << CA{1,2,3, 0} << endl; 
} 

error: taking address of temporary array (g++-4.7.2 -std=gnu++11)

Aggiornamento 2:

Penso (forse) che cosa sta succedendo è che i letterali stringa sono appositamente benedetti come lvalues ​​, tuttavia gli array temporanei sono valori di riferimento e pertanto non è possibile prendere il proprio indirizzo. Questa è un'ipotesi, però, non ne sono sicuro.

Update 3:

realtà che dovrebbe essere sbagliato penso:

An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.

+0

Quale sarebbe il vantaggio di utilizzare una matrice temporanea senza nome invece di una costante denominata? Non fa molto per la leggibilità. –

+0

"C'è un modo per specificare un array senza nome temporaneo con un elenco di inizializzatore?" Bene, a parte il materiale 'typedef' già risposto qui sotto,' std :: initializer_list' fa esattamente questo, se lo passi a qualcosa che può gestire qualsiasi intervallo o ha un sovraccarico specifico. –

risposta

5

Si utilizza un typedef e poi dire

ArrayType{1, 2, 3, 0} 

utilizzare alternativa un modello alias e poi

AliasTemplate<char[]>{1, 2, 3, 0} 
+0

Vedere l'aggiornamento - "prendere l'indirizzo della matrice temporanea"? –

+1

@user fantastico, questo è quello che volevi! se vuoi capire perché questo avviso è dato, ti consiglio una seconda domanda. –

+0

È un errore, non un avvertimento. –

13

1) Ho sofferto con questo problema per qualche tempo. Compilare il seguente programma, g ++ 4.7.1 (tdm64-1) dà l'errore: "teste1.cpp: 6: 33: errore: prendere l'indirizzo di array temporaneo"

#include <iostream> 
#include <cstring> 
using namespace std; 
int main() 
{ char t[]={1,2,3,0}; 
    if (strcmp((char[]){1,2,3,0},t)==0) //error 
    cout << "equal\n"; 
    else 
    cout << "different\n"; 
} 

Tuttavia, se si aggiunge la parola chiave " const", l'errore scompare e il programma viene eseguito senza intoppi:

if (strcmp((const char[]){1,2,3,0},t)==0) //correct 

2) In alcuni casi, semplicemente aggiungendo la parola chiave 'const' può non essere sufficiente. Ad esempio, g ++ 4.7.1 dà "l'errore: prendere l'indirizzo di array temporaneo" quando si compila il seguente programma:

#include <iostream> 
#include <cstring> 
using namespace std; 

void f(char* p) 
{ for (int i=0; p[i]!=0; i++) 
    cout << int(p[i]) << " "; 
    cout << endl; 
} 

int main() { 
    f((char[]){1,2,3,0}); // error 
} 

Se si aggiunge la parola chiave "const", il compilatore dà un altro tipo di errore: "conversione non valida da 'const char *' a 'char *' [-fpermissive] ":

f((const char[]){1,2,3,0}); //error 

per compilare correttamente il programma, è possibile compilarlo con l'opzione "-fpermissive" o fare una conversione di tipo esplicita:

f((char*)(const char[]){1,2,3,0}); // correct 
+0

costanti come quello è brutto, oltre a invalidare l'uso e lo scopo di const. – ted

+3

Questo potrebbe funzionare per alcune versioni di g ++, ma tenere presente che questa soluzione non è ben strutturata in C++ ('(char []) {1,2,3,0}' <- i letterali composti sono C> = 99 ma non sono consentiti in C++ e la sintassi non è consentita per introdurre una temporanea in C++, vedere [la mia risposta al commento di Johannes] (http://stackoverflow.com/questions/15458883/using-array-init-list-as-temporary- in-C11 # comment24292271_15458897)). La modifica del 'const char []' passato introdurrebbe un comportamento indefinito. In questo esempio, 'f' non modifica il parametro, quindi la firma della funzione dovrebbe essere' void f (const char *); '. – dyp

+0

Infatti, la mia soluzione compila ed esegue correttamente in g ++ ma non in Visual C. –

2

Sembra che questo problema possa essere risolto usando C++ 11 "move". Compilazione in g ++ 4.8.1 il programma:

#include <iostream> 
#include <cstring> 
using namespace std; 

typedef char CA[]; 
int main() { 
    cout << CA{'a','b','c',0} << endl; 
} 

risultati in "errore: prendere l'indirizzo della matrice temporanea". Tuttavia, utilizzando "sposta":

cout << move(CA{'a','b','c',0}) << endl; 

il programma viene compilato e viene eseguito correttamente. Il compilatore deve essere richiamato per utilizzare C++ 11 dialetto:

g++ prog1.cpp -o prog.exe -std=c++11 

Analogamente,

#include <iostream> 
#include <cstring> 
using namespace std; 
int main() 
{ char t[]={1,2,3,0}; 
    if (strcmp(move((char[]){1,2,3,0}) ,t)==0) //OK 
    cout << "equal\n"; 
    else 
    cout << "different\n"; 
} 

compila e gira correttamente, utilizzando -std = C++ 11 bandiera.

Problemi correlati