auto mit String-Literalen

Lesezeit: 4 Minuten
#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 n const 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


auto mit String Literalen
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 == &y kann 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

auto mit String Literalen
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:

const char m[]          = "ABC";

const char n[sizeof(m)] = m; //error

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

1641733294 331 auto mit String Literalen
konstantin

Wenn x als Array abgeleitet werden soll, können Sie

decltype(auto) x = "hello world";

  • x wird hier als Verweis auf ein Array abgeleitet.

    – HolyBlackCat

    17. Mai ’20 um 17:21

.

211980cookie-checkauto mit String-Literalen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy