2013-03-17 4 views
19

Ich kann eine benannte Variable mit einem Array erstellen, wie folgt:Verwenden Array-Init-Liste als temporäre in C++ 11?

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

jedoch folgendes nicht funktioniert:

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

Gibt es irgendeine Art und Weise eine temporäre unbenannte Array mit einer Initialisiererliste angeben ? (In diesem Fall wird ein Stringliteral funktionieren würde, aber für andere Arrays als char-Arrays?)

Update:

#include <iostream> 
#include <cstring> 

using namespace std; 

typedef char CA[]; 

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

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

Update 2:

Ich denke (vielleicht) was passiert ist, dass String-Literale besonders gesegnet sind als lvalues ​​, jedoch temporäre Arrays sind prvalues ​​, und als solche können Sie nicht ihre Adresse nehmen. Das ist eine wilde Vermutung, aber ich bin mir nicht sicher.

Update 3:

das sollte eigentlich falsch sein denke ich:

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

Welchen Vorteil hätte die Verwendung eines unbenannten temporären Arrays anstelle einer benannten Konstante? Es macht nicht viel zur Lesbarkeit. –

+0

"Gibt es eine Möglichkeit, ein temporäres unbenanntes Array mit einer Initialisierungsliste anzugeben?" Nun, abgesehen von den 'typedef'-Dingen, die bereits unten beantwortet wurden, tut' std :: initializer_list' genau das, wenn Sie es an etwas übergeben, das mit jedem Bereich umgehen kann oder eine spezifische Überladung hat. –

Antwort

5

Ja typedef verwenden und sagen dann

ArrayType{1, 2, 3, 0} 

Alternativ einen Alias-Vorlage verwenden und dann

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

Siehe Update - "Adresse des temporären Arrays übernehmen"? –

+1

@user toll, das ist was du wolltest! Wenn Sie verstehen wollen, warum diese Warnung gegeben wird, empfehle ich eine zweite Frage. –

+0

Es ist ein Fehler, keine Warnung. –

13

1) Ich litt seit einiger Zeit unter diesem Problem. Kompilieren Sie das folgende Programm, g ++ 4.7.1 (tdm64-1) gibt den Fehler: "teste1.cpp: 6: 33: Fehler: unter Adresse der temporären Matrix"

#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"; 
} 

Wenn Sie jedoch das Stichwort hinzufügen " const“, verschwindet der Fehler und das Programm läuft:

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

2) In einigen Fällen nur das Stichwort Hinzufügen‚const‘nicht genug sein kann. Zum Beispiel g ++ 4.7.1 gibt „Fehler: Adresse des temporären Arrays unter“, wenn Sie das folgende Programm kompiliert:

#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 
} 

Wenn Sie das Stichwort „const“ hinzufügen, gibt der Compiler eine andere Art von Fehler: „ungültige Umwandlung von 'const char *' auf 'char *' [-fpermissive]: -fpermissive ""

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

um das Programm erfolgreich zu kompilieren, können Sie entweder mit der Option kompilieren" oder eine explizite Typumwandlung machen:

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

Const Casting wie das ist hässlich, neben der Ungültigkeit der Verwendung und Zweck von const. – ted

+3

Dies kann für einige g ++ - Version funktionieren, aber bedenken Sie, dass diese Lösung nicht wohlgeformt ist. C++ ('(char []) {1,2,3,0}' <- zusammengesetzte Literale sind C> = 99, aber nicht erlaubt in C++, und die Syntax darf keine temporäre in C++ einführen, siehe [mein Kommentar zu Johannes 'Antwort] (http://stackoverflow.com/questions/15458883/using-array-init-list-as-temporary- in-c11 # Kommentar24292271_15458897)). Das Ändern des übergebenen 'const char []' würde zu undefiniertem Verhalten führen. In diesem Beispiel ändert 'f' den Parameter nicht, daher sollte die Funktionssignatur' void f (const char *); 'sein. – dyp

+0

Tatsächlich kompiliert und führt meine Lösung korrekt in g ++, aber nicht in Visual C aus. –

2

Es scheint, dass dieses Problem mit C++ 11 "move" gelöst werden kann. Kompilieren in g ++ 4.8.1 das Programm:

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

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

führt zu "Fehler: Adresse der temporären Array übernehmen". Verwenden Sie jedoch "verschieben":

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

das Programm kompiliert und läuft ordnungsgemäß. Der Compiler muß aufgerufen werden, C++ 11 Dialekt verwenden:

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

ähnlich

#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"; 
} 

kompiliert und auch korrekt ausgeführt wird, unter Verwendung von -std = C++ 11-Flag.