Suche…


Bemerkungen

Das Schlüsselwort auto ist ein Typname, der einen automatisch abgeleiteten Typ darstellt.

Es war bereits ein reserviertes Schlüsselwort in C ++ 98, das von C geerbt wurde. In alten Versionen von C ++ konnte explizit angegeben werden, dass eine Variable eine automatische Speicherdauer hat:

int main()
{
  auto int i = 5; // removing auto has no effect
}

Diese alte Bedeutung ist jetzt entfernt.

Grundlegende Auto-Probe

Das Schlüsselwort auto bietet die automatische Ableitung des Typs einer Variablen.

Dies ist besonders praktisch, wenn Sie lange Typnamen verwenden:

std::map< std::string, std::shared_ptr< Widget > > table;
// C++98
std::map< std::string, std::shared_ptr< Widget > >::iterator i = table.find( "42" );
// C++11/14/17
auto j = table.find( "42" );

mit bereichsbasierter für Schleifen :

vector<int> v = {0, 1, 2, 3, 4, 5};
for(auto n: v)
    std::cout << n << ' ';

mit lambdas :

auto f = [](){ std::cout << "lambda\n"; };
f();        

um die Wiederholung des Typs zu vermeiden:

auto w = std::make_shared< Widget >();

um überraschende und unnötige Kopien zu vermeiden:

auto myMap = std::map<int,float>();
myMap.emplace(1,3.14);

std::pair<int,float> const& firstPair2 = *myMap.begin();  // copy!
auto const& firstPair = *myMap.begin();  // no copy!

Der Grund für die Kopie ist, dass der zurückgegebene Typ tatsächlich std::pair<const int,float> !

Auto- und Ausdrucksvorlagen

auto kann auch Probleme verursachen, wenn Ausdrucksvorlagen ins Spiel kommen:

auto mult(int c) {
    return c * std::valarray<int>{1};
}

auto v = mult(3);
std::cout << v[0]; // some value that could be, but almost certainly is not, 3.

Der Grund ist, dass operator* on valarray Ihnen ein Proxy-Objekt gibt, das sich auf das valarray bezieht, um eine valarray Bewertung valarray . Wenn Sie auto , erstellen Sie eine baumelnde Referenz. Statt mult hatte std::valarray<int> , dann würde der Code definitiv 3 drucken.

auto, const und referenzen

Das auto Schlüsselwort selbst repräsentiert einen Werttyp, ähnlich wie int oder char . Sie kann mit dem Schlüsselwort const und dem Symbol & geändert werden, um einen konstanten Typ oder einen Referenztyp darzustellen. Diese Modifikatoren können kombiniert werden.

In diesem Beispiel ist s ein Wertetyp (sein Typ wird als std::string ), sodass jede Iteration der for Schleife einen String aus dem Vektor in s kopiert .

std::vector<std::string> strings = { "stuff", "things", "misc" };
for(auto s : strings) {
    std::cout << s << std::endl;
}

Wenn der Hauptteil der Schleife s ändert (z. B. durch Aufrufen von s.append(" and stuff") ), wird nur diese Kopie geändert, nicht das ursprüngliche s.append(" and stuff") von strings .

Wenn s jedoch mit auto& deklariert ist, ist es ein Referenztyp (wird als std::string& ), so dass ihm bei jeder Wiederholung der Schleife eine Referenz auf einen String im Vektor zugewiesen wird:

for(auto& s : strings) {
    std::cout << s << std::endl;
}

Im Hauptteil dieser Schleife wirken sich Änderungen an s direkt auf das Element der strings , auf die es verweist.

Wenn s als const auto& deklariert ist, ist es schließlich ein const-Referenztyp. Dies bedeutet, dass ihm bei jeder Iteration der Schleife ein const-Referenzwert für einen String im Vektor zugewiesen wird:

for(const auto& s : strings) {
    std::cout << s << std::endl;
}

Innerhalb dieser Schleife können s nicht geändert werden (dh es können keine Nicht-Konstanten-Methoden aufgerufen werden).

Wenn Sie auto mit bereichsbasierten for Schleifen verwenden, ist es im Allgemeinen ratsam, const auto& wenn der Schleifenrumpf die überlaufene Struktur nicht ändert, da dadurch unnötige Kopien vermieden werden.

Hinterlegter Rückgabetyp

auto wird in der Syntax für abschließende Rückgabetypen verwendet:

auto main() -> int {}

das ist äquivalent zu

int main() {}

Meistens nützlich in Verbindung mit decltype , um Parameter anstelle von std::declval<T> :

template <typename T1, typename T2>
auto Add(const T1& lhs, const T2& rhs) -> decltype(lhs + rhs) { return lhs + rhs; }

Generisches Lambda (C ++ 14)

C ++ 14

C ++ 14 erlaubt die Verwendung von auto in Lambda-Argumenten

auto print = [](const auto& arg) { std::cout << arg << std::endl; };

print(42);
print("hello world");

Das Lambda entspricht meistens

struct lambda {
    template <typename T>
    auto operator ()(const T& arg) const {
        std::cout << arg << std::endl;
    }
};

und dann

lambda print;

print(42);
print("hello world");

Auto- und Proxy-Objekte

Manchmal verhält sich auto möglicherweise nicht ganz so, wie es von einem Programmierer erwartet wurde. Der Typ leitet den Ausdruck ab, auch wenn der Typabzug nicht richtig ist.

Wenn zum Beispiel Proxy-Objekte im Code verwendet werden:

std::vector<bool> flags{true, true, false};
auto flag = flags[0];
flags.push_back(true);

Hier flag würde nicht bool , aber std::vector<bool>::reference , da für bool Spezialisierung von Template - vector des operator [] gibt ein Proxy - Objekt mit Konvertierungsoperator operator bool definiert.

Wenn flags.push_back(true) den Container ändert, kann diese Pseudo-Referenz enden und sich auf ein Element beziehen, das nicht mehr vorhanden ist.

Es macht auch die nächste Situation möglich:

void foo(bool b);

std::vector<bool> getFlags();

auto flag = getFlags()[5];
foo(flag);

Der vector wird sofort gelöscht. flag ist also eine Pseudo-Referenz auf ein Element, das gelöscht wurde. Der Aufruf von foo ruft ein undefiniertes Verhalten auf.

In solchen Fällen können Sie eine Variable mit auto deklarieren und initialisieren, indem Sie den Typ ausführen, den Sie ableiten möchten:

auto flag = static_cast<bool>(getFlags()[5]);

an diesem Punkt ist es jedoch sinnvoller, auto durch bool ersetzen.

Ein weiterer Fall, in dem Proxy-Objekte Probleme verursachen können, sind Ausdrucksvorlagen . In diesem Fall sind die Vorlagen manchmal nicht so ausgelegt, dass sie aus Effizienzgründen über den aktuellen Vollausdruck hinausgehen. Die Verwendung des Proxy-Objekts beim nächsten bewirkt ein undefiniertes Verhalten.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow