#include <iostream>
#include <typeinfo>
int main()
{
const char a[] = "hello world";
const char * p = "hello world";
auto x = "hello world";
if (typeid(x) == typeid(a))
std::cout << "It's an array!n";
else if (typeid(x) == typeid(p))
std::cout << "It's a pointer!n"; // this is printed
else
std::cout << "It's Superman!n";
}
Warum ist x als Zeiger abgeleitet, wenn String-Literale eigentlich Arrays sind?
Ein schmales String-Literal hat den Typ “Array of nconst char” [2.14.5 String Literals [lex.string] §8]
Meine Lesart der Norm, für auto und deklarierter Typ scheinen darauf hinzuweisen, dass es sich wie erwartet um ein Array handeln sollte. Sie sagen eindeutig, dass es auch wie ein Vorlagenparameter aufgelöst wird, was sicherlich ein Array wäre (obwohl ich es gerade getestet habe und in GCC die Vorlagenform des obigen auch “Zeiger” meldet).
– edA-qa mort-ora-y
18. August ’12 um 7:34
Sellibitze
Das Merkmal auto basiert auf der Ableitung von Vorlagenargumenten und die Ableitung von Vorlagenargumenten verhält sich gleich, insbesondere gemäß §14.8.2.1/2 (C++11-Standard):
Wenn P kein Referenztyp ist
Wenn A ein Array-Typ ist, wird der durch die Array-zu-Zeiger-Konvertierung erzeugte Zeigertyp anstelle von A für die Typableitung verwendet
Wenn Sie den Typ des Ausdrucks wünschen x um ein Array-Typ zu sein, fügen Sie einfach hinzu & nach auto:
auto& x = "Hello world!";
Dann ist die auto Platzhalter wird abgeleitet zu sein const char[13]. Dies ist auch ähnlich wie bei Funktionsschablonen, die eine Referenz als Parameter verwenden. Nur um Verwirrung zu vermeiden: Der deklarierte Typ von x ist Hinweis-zu-Array.
Beachten Sie, dass das bedeutet x Hier ist kein Array, sondern eine Referenz auf ein Array. Der feine Unterschied ist, dass nach auto& x = "a"; auto& y = "a";, &x == &ykann geben true zurück, je nachdem, ob die beiden unterschiedlichen Zeichenfolgenliterale zusammengeführt werden.
– Benutzer743382
18. August ’12 um 8:14
@hvd: Richtig, deshalb habe ich ausdrücklich “Typ des Ausdrucks x” anstelle von “deklarierter Typ von x” gesagt. Aber es ist sicherlich erwähnenswert. Danke. 🙂
– sellibitze
18. August ’12 um 8:31
auto&& x = "Hello world!"; ist auch eine Möglichkeit (und liefert eine lvalue-Referenz auf ein Array, genau wie auto& tut in diesem Fall).
– Luc Danton
18. August ’12 um 8:33
@LucDanton Richtig, ich vergesse immer, dass Zeichenfolgenliterale Lvalues sind.
– Fredoverflow
18. August ’12 um 8:59
Nawaz
Warum wird x als Zeiger abgeleitet, wenn Stringliterale eigentlich Arrays sind?
Wegen der Array-to-Pointer-Konvertierung.
Wenn x ist als Array abzuleiten, nur wenn Folgendes erlaubt ist:
In C++ kann ein Array nicht mit einem anderen Array initialisiert werden (wie oben). In solchen Fällen zerfällt das Quellarray in einen Zeigertyp, und Sie können stattdessen Folgendes tun:
const char* n = m; //ok
Die Regeln für die Typinferenz mit auto entspricht den Regeln der Typableitung in der Funktionsvorlage:
template<typename T>
void f(T n);
f(m); //T is deduced as const char*
f("ABC"); //T is deduced as const char*
auto n = m; //n's type is inferred as const char*
auto n = "ABC"; //n's type is inferred as const char*
§7.1.6.4/6 sagt über auto Bezeichner:
Der für die Variable d abgeleitete Typ ist dann der abgeleitete A, der mit den Regeln der Musterargumentableitung aus einem Funktionsaufruf (14.8.2.1) …
x ist nicht initialisiert mit a. x wird initialisiert mit "hello world", das ein gültiger Initialisierer für ein Array von char ist.
– Benutzer743382
18. August ’12 bei 7:51
Sicher tut es das. Deine Antwort erklärt nur warum auto x = a; machen würden x ein Hinweis, aber darum geht es nicht.
– Benutzer743382
18. August ’12 um 7:52
Bis auf einen Unterschied: Sie sind gültige Initialisierer für char-Arrays. Du hast const char m[] = "ABC"; in Ihrer eigenen Antwort, genauso wie Sie sagen, dass Arrays keine gültigen Initialisierer für andere Arrays sind!
– Benutzer743382
18. August ’12 um 7:55
Ihre bearbeitete Version scheint den GCC zu entsprechen, selbst wenn Sie Referenzqualifizierer hinzufügen: template <typename T> void f(T&&); f("abc"); T wird als Array abgeleitet. Gleiches für auto&& x = "abc";
– Benutzer743382
18. August ’12 um 8:04
@hvd: Zitat aus der Spezifikation hinzugefügt.
– Nawaz
18. August ’12 um 8:21
konstantin
Wenn x als Array abgeleitet werden soll, können Sie
Meine Lesart der Norm, für
auto
und deklarierter Typ scheinen darauf hinzuweisen, dass es sich wie erwartet um ein Array handeln sollte. Sie sagen eindeutig, dass es auch wie ein Vorlagenparameter aufgelöst wird, was sicherlich ein Array wäre (obwohl ich es gerade getestet habe und in GCC die Vorlagenform des obigen auch “Zeiger” meldet).– edA-qa mort-ora-y
18. August ’12 um 7:34