2015-01-03 15 views
7

In kann Initialisierungslisten zum Initialisieren von Parametern in Funktionen verwendet werden. Was ist der Zweck davon? Kann das nicht mit konstanten Vektoren gemacht werden? Was ist der Unterschied der beiden unten aufgeführten Programme?Initialisierungsliste vs. Vektor

Verwendung Initialisiererliste:

#include <iostream> 

using namespace std; 

int sumL(initializer_list<int> l){ 
    int sum = 0; 
    for (const auto i: l){ 
     sum += i; 
    } 
    return sum; 
} 

int main(){ 

    cout << sumL({1, 2, 3}) << "\n"; 

    return 0; 
} 

const Vektor unter Verwendung von:

#include <iostream> 
#include <vector> 

using namespace std; 

int sumV(const vector<int> l){ 
    int sum = 0; 
    for (const auto i: l){ 
     sum += i; 
    } 
    return sum; 
} 

int main(){ 

    cout << sumV({1, 2, 3}) << "\n"; 

    return 0; 
} 
+2

Der zweite Code erfordert mehr als benötigt (und der Vektor wird auch mit einer Initialisiererliste erstellt) –

+0

Offtopic: Beachten Sie, dass Sie eine Kopie des Vektors erstellen, d. H. Sie haben keine Referenz & verwendet. Das Gleiche gilt für die for-Schleife, jetzt ist es nur ein int, aber bei größeren Objekten vermeidet die Referenz, dass Sie jedes Objekt im Vektor kopieren. – Michiel

Antwort

6

Die gemeinsame Verwendung von std::initializer_list ist als Argument Konstruktoren Behälter (und ähnliche) Klassen, so dass bequem der Initialisierung dieser Container aus ein paar Objekten des gleichen Typs. Natürlich können Sie std::initializer_list verwenden und dann die gleiche {} Syntax verwenden.

Da eine std::initializer_list eine feste Größe hat, erfordert sie keine dynamische Zuweisung und kann daher effizient implementiert werden. Eine std::vector erfordert andererseits eine dynamische Speicherzuweisung. Selbst in Ihrem einfachen Beispiel ist es unwahrscheinlich, dass der Compiler diesen Overhead optimiert (vermeiden Sie den Vermittler std::vector und seine dynamische Speicherzuweisung). Ansonsten gibt es keinen Unterschied im Ergebnis Ihrer Programme (obwohl Sie ein const std::vector<int>& Argument verwenden sollten, um eine Kopie und die damit verbundene dynamische Speicherzuweisung zu vermeiden).

3

Die Semantik der beiden sind sehr unterschiedlich. Die initializer_list hat Pointer-Semantik, während die vector Wert Semantik hat.

In Ihrem ersten Beispiel wird der Compiler Code ähnlich den folgenden erzeugen:

int const __temp_array[3] = {1, 2, 3}; 
cout << sumL(std::initializer_list<int>(__temp_array, __temp_array + 3)) << "\n"; 

Die in erklärt [dcl.init.list]/5. Wie Sie sehen können, haben Sie innerhalb sumL Zugriff auf const Zeiger auf die Elemente der braced-init-Liste, das heißt, Sie haben keine andere Option, als die Elemente aus der Liste zu kopieren.

Bei sumV Sie std::moved die Elemente aus der vector wenn nötig haben könnte (vorausgesetzt, der Typ-Parameter ist nicht const).

In ähnlicher Weise führt das Kopieren der initializer_list flache Kopien durch, d. H. Nur die Zeiger werden kopiert, während das Kopieren der vector natürlich bedeutet, dass die Elemente kopiert werden.

In diesem Beispiel macht keiner der obigen Punkte wirklich einen Unterschied, außer dass das Konstruieren der vector dynamische Speicherzuweisung erfordert, während das Konstruieren der nicht funktioniert.

3

initializer_list verwendet optimalen Speicherort und verhindert unnötige Aufrufe, es wurde entwickelt, um leicht zu sein, während mit vector gibt es eine Heap-Zuweisung und es können mehr Kopien/Verschiebungen gemacht werden.

1

initalizer_list ist kein verallgemeinerter Container wie std :: vector. Sein Hauptzweck ist die Objektinitialisierung. Wenn das niedrige Overhead und keine Heap-Zuweisung für Sie attraktiv ist, würde ich vorschlagen, std :: array zu betrachten. Es ist ein Stack zugewiesenes Array fester Größe, das alle Annehmlichkeiten eines STL-Containers hat, der im Wesentlichen ein dünner Wrapper oben auf einem C-Array ist.

Verwandte Themen