Vektoren initialisieren?
-
Danke erst mal für die Antwort, also ich habe VS vor ein paar Tagen gepatcht und es sollte schon auf dem neusten Stand sein.
double data[] = {1.1, 2.2, 3.3, 4.4, 5.5}; vector<double> vec(data, data + sizeof(data)/sizeof(*data));
Wärst du vielleicht so nett und würdest den Code ein bisschen erläutern?
Also ich verstehe schon, dass ein Array vom typ double erstellt wurde um den Vektor zu initialisieren, aber mir ist nicht ganz klar wasvec(data, data + sizeof(data)/sizeof(*data));
das zu bedeuten hat.
-
Jain, SeppJ.
Ich habe hier VS2012 mit Update 3, dort ist das nicht möglich. Auch Header wie initializer_list sind noch unbekannt.
Aber es gibt tatsächlich ein Update von November 2012, welches wohl etwaige Features aus C++11 hinzufügen soll. hier
Aber bei mir war das noch schwer buggy. Erstens ist IntelliSense noch überhaupt nicht daran geknüpft (sehr viel wurde in meinem bestehenden Code als flasch unterstrichen) und auch dann kamen nur noch Fehlermeldungen beim compilen. Ich habe aber auch den Fehler gemacht, das Update während eines laufenden Projekts auszuprobieren (mir gings eig um Varadische Templates konkret).
-
Fabolous12 schrieb:
Also ich verstehe schon, dass ein Array vom typ double erstellt wurde um den Vektor zu initialisieren, aber mir ist nicht ganz klar was
vec(data, data + sizeof(data)/sizeof(*data));
data = Zerfällt zu einem Zeiger, der auf das erste Element des Arrays zeigt.
sizeof(data) = Die Größe des Arrays.
*data = Die Größe eines Elements im Array.
sizeof(data)/sizeof(*data) = Anzahl Elemente im Array
data + sizeof(data)/sizeof(*data) = Zeiger aufs Arrayende (eins nach dem letzen Arrayelement)
-
Skym0sh0 schrieb:
Aber es gibt tatsächlich ein Update von November 2012, welches wohl etwaige Features aus C++11 hinzufügen soll. hier
Naja, das ist so ne Sache. Die haben zwar die Core Language upgedatet, nicht aber die STL. Du kannst noch immer kein std::vector via initializer_list erstellen. Fail
-
Fabolous12 schrieb:
Wärst du vielleicht so nett und würdest den Code ein bisschen erläutern?
Also ich verstehe schon, dass ein Array vom typ double erstellt wurde um den Vektor zu initialisieren, aber mir ist nicht ganz klar wasvec(data, data + sizeof(data)/sizeof(*data));
das zu bedeuten hat.
Da geschehen gleich mehrere Sachen, die man als Anfanger vielleicht noch nicht so kennt:
1. Der Konstruktor des vectors, der hier benutzt wird, ist die dritte Variante in dieser Referenz:
http://www.cplusplus.com/reference/vector/vector/vector/
Da wird ein "Iterator" (d.h. ein allgemeines, zeigerartiges Objekt) auf den Anfang und das Ende eines Bereiches genommen und der vector dann mit dem Inhalt dieses Bereiches initialisiert.
2. Der Anfang des Bereiches ist hier "data". Arrays in C++ sind ein bisschen komisch, anders als alle "normalen" Objekte, die man so kennt. Das hat historische Gründe. Ein Array kann, wenn es der Kontext verlangt, in einen Zeiger auf sein erstes Element aufgefasst werden. Ein Array als Funktionsparameter ist ein solcher Kontext*, wir bekommen also einen Zeiger auf den Anfang des Arrays. Das ist daher genau der Iterator auf den Anfang des Bereichs mit den Initialisierungsdaten, den wir möchten.
3. Wir brauchen noch das Ende des Bereiches. Genauer, eins hinter das Ende (siehe Referenz. Das ist die übliche Konvention bei der Angabe von Bereichen: Man hat den Anfang und das Element hinter dem Ende). Da wir wissen, dass das Array hier 5 Elemente hat, könnten wir auch einfach&data[5]
(Adressoperator) oderdata + 5
(Stichwort: Zeigerarithmetik. Das "data" wird wieder zu einem Zeiger auf das erste Element und dann zählen wir 5 dazu) schreiben. Aber das ist doof, wenn sich die Anzahl mal ändert, dann musst du an mehreren Stellen Änderungen vornehmen (bei der Initialisierung des Arrays und bei der Initialisierung des vectors) und aufpassen, dass alles zusammenpasst. Daher lassen wir den Compiler zählen. sizeof(data) ist die Länge des Arrays in Einheiten der char-Größe. Aber wie viele Elemente sind das? Klar: Gesamtgröße geteilt durch die Größe eines Elementes ist die Anzahl der Elemente. Wir könnten hier also durch sizeof(double) teilen. Aber auch das ist doof, wenn sich später der Datentyp mal ändert, dann musst du wieder an mehreren Stellen Änderungen konsistent halten. Daher lassen wir wieder den Compiler das selbst heraus finden:sizeof(*data)
. Da wenden wir Pointerdereferenzierung (das Sternchen) auf data an. Pointerdereferenzierung auf ein Array macht keinen Sinn, das data wird wieder zu einem Pointer auf das erste Element. Soclh ein Pointer dereferenziert ist das erste Element selber. Und sizeof des ersten Elementes ist genau das, was wir hier suchen, denn alle Elemente sind gleich groß.*: Solch ein Kontext liegt fast immer vor, die Ausnahmen kann man an einer Hand abzählen. sizeof ist eine davon.
-
Hol dir VS 2013, dort gehts...
-
was habe ich für alternativen um Vektoren zu initialisieren?
Swordfish hat einmal eine (mMn. unschöne) Möglichkeit gepostet:
// Nicht-C++11 Krücke: template< typename T > class make_vector_t { private: std::vector< T > data; public: make_vector_t( T const & value ) { data.push_back( value ); } make_vector_t< T > & operator,( T const & value ) { data.push_back( value ); return *this; } operator std::vector< T >() { return data; } }; template< typename T > make_vector_t< T > make_vector( T const & value ) { return make_vector_t< T >( value ); }
Beispiel (ungetestet):
std::vector<int> foo(( make_vector(0), 1, 2, 3 ));
-
Danke für die ausführliche Erklärung, ich habe das jetzt ziemlich gut verstanden. Auch wie man mit sizeof zum Beispiel nur die Größe eines normalen Arrays ermittelt.
Nochmal dickes Dankeschön !
-
Sone schrieb:
// Nicht-C++11 Krücke: template< typename T > class make_vector_t { private: std::vector< T > data; public: make_vector_t( T const & value ) { data.push_back( value ); } make_vector_t< T > & operator,( T const & value ) { data.push_back( value ); return *this; } operator std::vector< T >() { return data; } }; template< typename T > make_vector_t< T > make_vector( T const & value ) { return make_vector_t< T >( value ); }
Beispiel (ungetestet):
std::vector<int> foo(( make_vector(0), 1, 2, 3 ));
Funzt, ist allerdings wahrlich unschön, einerseits wegen des schrittweisen Aufbaus des Vektors, andernseits wegen der Parameterübergabe, welche zusätzliche Klammern erfordert und der übergebene Wert an make_vector zwingend genau den gleichen Typ wie der Zielvektor haben muss.
-
Ich würde die angedeutete aber nicht gezeigte Methode mit begin und end bevorzugen.
double data[] = {1.1, 2.2, 3.3, 4.4, 5.5}; //vector<double> vec(data, data + sizeof(data)/sizeof(*data)); // Oder schöner mit begin und end, falls das unterstüzt wird. vector<double> vec(begin(data), end(data)); //sieht hübscher aus
-
Die C++03-Variante: Boost.Assign
-
-
Vielleicht ist std::array ja etwas für dich, denn da funktioniert die Initalisierung auch in Visual Studio.
-
Die Initialisierung funktioniert generell in Visual Studio, nur eben nicht mit der Version, die er benutzt...
-
nwp3 schrieb:
Ich würde die angedeutete aber nicht gezeigte Methode mit begin und end bevorzugen.
double data[] = {1.1, 2.2, 3.3, 4.4, 5.5}; //vector<double> vec(data, data + sizeof(data)/sizeof(*data)); // Oder schöner mit begin und end, falls das unterstüzt wird. vector<double> vec(begin(data), end(data)); //sieht hübscher aus
Ich würde vermuten, dass ein Compiler, der initializer lists nicht kennt, auch kein begin und end kennt. Daher habe ich es nur angedeutet. Wenn man initializer lists hat, sind diese hier zu bevorzugen.
Mag sein, dass diese spezielle MSVC-Version genau so ein Grenzfall ist, wo eines vorhanden ist, das andere nicht. Das ist dann aber schon sehr speziell.
dot schrieb:
Die Initialisierung funktioniert generell in Visual Studio, nur eben nicht mit der Version, die er benutzt...
Ich hatte da heute Morgen, als ich sagte, dass es ein Update gäbe, meine ich gelesen, dass es wirklich nur vector betrifft.
-
MSVC kennt begin/end seit zwei Revisionen, Initialiser Lists gibts dagegen erst in der kommenden Version, die im Moment als Preview verfügbar ist...
SeppJ schrieb:
dot schrieb:
Die Initialisierung funktioniert generell in Visual Studio, nur eben nicht mit der Version, die er benutzt...
Ich hatte da heute Morgen, als ich sagte, dass es ein Update gäbe, meine ich gelesen, dass es wirklich nur vector betrifft.
Ich habs natürlich ausprobiert, zumindest mit meinem simplen Testbeispiel gabs in VS 2013 keine Probleme...
-
SeppJ schrieb:
Fabolous12 schrieb:
Hey, ich arbeite zur Zeit mit Visual Studio 2012 - Express und habe leider noch nicht die Möglichkeit Vektoren folgendermaßen zu initialisieren :
Laut Patchnotes sollte im herbst 2012 ein Update erschienen sein, welches dies ermöglicht. Ich habe VS nicht, um das zu überprüfen, aber würde mich wundern, wenn das nicht stimmen würde.
Herbert Sutter ist alles zuzutrauen:
http://blogs.msdn.com/b/vcblog/archive/2012/11/02/visual-c-c-11-and-the-future-of-c.aspx
Versprochen und nicht geliefert, also Note 6 setzen.SeppJ schrieb:
Einfach mal ein Update machen?
Hilft nichts, im CTP für Update 1 versprochen aber selbst im Update 3 ein halbes Jahr später immer noch keine initializer_lists.
Ist sowieso Schwachsinn, ein Preview zu einem Update.double data[] = {1.1, 2.2, 3.3, 4.4, 5.5}; vector<double> vec(data, data + sizeof(data)/sizeof(*data)); // Oder schöner mit begin und end, falls das unterstüzt wird.
Im VisualC++ geht es auch kürzer:
double data[] = {1.1, 2.2, 3.3, 4.4, 5.5}; vector<double> vec(data, data + _countof(data) );
Mit VS2013 funktioniert dann endlich auch:
vector<double> v1 = {1.1, 2.2, 3.3, 4.4, 5.5};
-
Wutz, richtig muß es aber wohl so geschrieben werden:
double data[] = {1.1, 2.2, 3.3, 4.4, 5.5}; vector<double> vec(data, data + _countof(data) );