Wie kann ich hier das Array mit Werte initialisieren?
-
Du suchst std::initializer_list aus dem 2011er-Standard
Du suchst ein C++ Tutorial
-
Solche Kommentare lässt du bitte schön (bei mir) in Zukunft bleiben. Ich weiß, dass ich Anfänger bin. Ich habe (mehrere) Tutorials und mittlerweile 2 Bücher zum durcharbeiten da, wo ich auch drüber bin!
Da ich aber eine anständige Frage hier drin formuliert habe, stehen mir DEFINITIV auch anständige Antworten ZU!
Genau wegen solchen Usern wie dir hab ich mich hier schon mal ziemlich aufregen müssen! Also bitte ich dich:
-> mich entweder ignorieren,
oder
-> solche Art von Kommentaren oder "Hilfe" einfach bleiben lassen!!!
Außer negativen Feedback bleibt mir aber noch über, ein großes Dankeschön an den User "Skym0sh0" zu geben. Der Beitrag hat mir sehr weitergeholfen! Danke!
Danke an alle bisherigen Beteiligten! Ich meld mich wieder
-
Anmerkungen zum Code:
#include<iostream> using namespace std; class myVec { private: double *v; //Zeiger, weil keine feste Größe!vist kein vernünftiger Name für ein Klassenelementint length;Nimm
size_t.public: myVec() //allgemeiner KonstruktorDas heißt Standardkonstruktor. Standard ohne T.
{ v = new double[1]; v[0] = 0;Warum 1 Element? Kein Element wäre logischer.
Nimm eine Initialisierungsliste.length = 0; } myVec(double *vec) //Vektorkonstruktorconstfehlt, die Länge des Arrays fehlt.
Warum nicht gleich ein Template-Konstruktor für Iteratoren?{ length = sizeof(vec)/sizeof(vec[0]);v = new double[length+1];Warum schon wieder 1 mehr als nötig?
for(int i=0; i<length; i++) { v[i] = vec[i]; }Tipp:
std::copy} myVec operator = (myVec& vec) //Überladung des =constfehlt. Der Rückgabetyp sollte eine Referenz sein.{ if(&vec != this) { delete v;deletepasst nicht zunew[].length = vec.length; v = new double[length+1];Schon wieder 1 mehr.
for(int i=0; i<length; i++) { v[i] = vec.v[i]; } } return *this; } }; int main() { myVec vec1; vec1 = {1,2,3,4,5};Das geht in C++11 mit
initializer_list. Du hast aber wahrscheinlich keinen Compiler, der das kann.system("pause"); return 0; }Warum hast du die Fehlermeldung nicht angegeben?
Eine Alternative sieht so aus:
const double args[] = {1, 2, 3}; std::vector<double> v(args, args + 3);Das kannst du nachbauen, wenn du Iteratoren verstanden hast.
-
Eine minimale Version könnte ungefähr so aussehen.
#include <algorithm> #include <initializer_list> #include <memory> #include <utility> #ifdef _MSC_VER #define noexcept #endif class myVec { public: typedef double value_type; typedef unsigned size_type; // construct/assign/destroy myVec() noexcept // default : data_(), size_() {} myVec(const myVec& other) // copy : data_( new value_type[other.size_] ), size_( other.size_ ) { std::copy( other.data_.get(), other.data_.get() + other.size_, data_.get() ); } myVec(myVec&& other) noexcept // move : data_( std::move( other.data_ ) ), size_( other.size_ ) { other.size_ = 0; } myVec(std::initializer_list<value_type> l) // list initialization (1) : data_( new value_type[l.size()] ), size_( l.size() ) { std::copy( l.begin(), l.end(), data_.get() ); } /* template<typename... T> myVec(T&&... arg) // list initialization (2) : data_( new value_type[sizeof...(arg)]{ ( std::forward<T>( arg ) )... } ), size_( sizeof...(arg) ) { } */ myVec& operator=(const myVec& rhs) // copy assign { myVec( rhs ).swap( *this ); // copy&swap return *this; } myVec& operator=(myVec&& rhs) noexcept // move assign { myVec( std::move( rhs ) ).swap( *this ); // move&swap // Besser als direktes swap( rhs ), weil so Resourcen bereits innerhalb der Funktion // freigegeben werden und nicht erst, wenn irgendwann mal der Destruktor des // Arguments aufgerufen wird. (der Move-Konstruktoraufruf kann nicht per 12.8/31 "wegoptimiert" werden) return *this; } // ~myVec_msvc() = default; // destroy // swap void swap(myVec& other) noexcept { using std::swap; swap( data_, other.data_ ); swap( size_, other.size_ ); } private: std::unique_ptr<value_type[]> data_; size_type size_; };Wobei Visual C++ 2010 List-Initialisierung noch nicht beherrscht - die erste Variante kompiliert zwar, wird aber nicht benutzt.
-
jetzt muss ich aber mal nachfragen, bin ja nicht einer derer die den neuen std sofort schlucken und alles ausprobieren (ja msvc user :D)
was ist eigentlich der ganze move kram? und rvalue referenzen und so?
-
@camper: ist noexcept nicht dasselbe wie throw() und damit schlecht weil langsam?
-
Und deine beiden op ='s kannst du durch diesen hier ersetzen:
myVec& operator = (myVec other) //noexcept? { swap(other); return *this; }Bin mir nur gerade nicht sicher, ob noexcept auch fürs Kopieren der Argumente gilt.
-
314159265358979 schrieb:
@camper: ist noexcept nicht dasselbe wie throw() und damit schlecht weil langsam?
Es hat den gleichen Effekt wie throw(). Das bedeutet alleridngs nicht per se, dass sich die Programmgeschwindigkeit dadurch ändern muss (positiv oder negativ). Neben anderen Änderungen verursacht in diesem Fall das Werfen einer Exception nicht mehr den Aufruf von unexpected, vielmehr wird terminate direkt aufgerufen, und es steht der Implementation frei, den Stack nur partiell oder sogar gar nicht aufzuräumen.
Viel wichtiger allerdings ist, dass diese Exceptionspezifikationen zwingend benötigt werden, sobald Algorithmen und Move-Semantik im Spiel ist.
Betrachte:#include <vector> #include <assert> using std::vector; struct Foo { Foo(const Foo&); // wirft evtl. Foo(Foo&&); // wirft evtl. }; struct Bar { Bar(const Bar&); // wirft evtl. Bar(Bar&&); }; int main() { vector<Foo> vfoo(10); assert(vfoo.capacity()==10); vfoo.push_back(Foo()); // Reallokation 10x kopieren + 1x hinzufügen vector<Bar> vbar(10); assert(vbar.capacity()==10); vbar.push_back(Bar()); // Reallokation 10x move + 1x hinzufügen };Im Gegensatz zu den alten Exceptionspezifikationen kann getestet werden, ob ein Ausdruck möglicherweise eine Exception werfen darf, und anhand des Ergebnisses kann man dann ggf. die optimale Implementation eines Algorithmus auswählen.
Die Art der Deklaration ist dafür irrelevantvoid foo() throw() void foo() noexcept void foo() noexcept(true)sind identisch. Man kann dann in Templates auch noch schlauer sein
template <typename T> struct Foo { void foo() noexcept(noexcept(declval<T>().do_something())) // foo ist noexcept, falls der Ausdruck declval<T>().do_something() keine Exception werfen darf - also die Funktion do_something für unser T noexcept ist // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ noexcept-Ausdruck ergibt true oder false // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ noexcept-Spezifikation };
-
wie schonmal gefragt: was zum teufel ist diese move semantik?
-
Lies einmal das hier, sowie die nachfolgenden Teile: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
-
Skym0sh0 schrieb:
wie schonmal gefragt: was zum teufel ist diese move semantik?
Eine Move-Operation ist eine Operation, bei der der Wert des Operaden destruktiv in ein Zielobjekt transferiert wird. Der Clou dabei ist, dass in vielen Fällen eine logische konstante Copy-Operation (bei der ein Duplikat der Ursprungsdaten erzeugt wird) durch eine solche Move-Operation ersetzt werden kann. Nämlich immer dann, wenn das Ursprungsobjekt nach der Kopieroperation nicht mehr weiter verwendet wird, in diesem Fall wird nämlich die durch das Move bedingte Veränderung des Ursprungsobjektes im Programm gar nicht bemerkt werden. Solche Objekte gibt es in C++ viele: immer dann wenn ein temporäres Objekt erzeugt wird (primär: als Rückgabewert einer Funktion) um ein anderes Objekt zu initialisieren. C++03 erlaubt bereits in vielen Fällen die Eliminierung der Kopieraktion (und dann wird nat. auch nicht gemoved), es gibt aber Ausnahmen, bei denen das nicht möglich ist. Auch bei Zuweisungen ist die Eliminierung i.d.R. nicht möglich.
Move-Semantik in C++11 erlaubt es, für einen bestimmten Typen zu definieren, wie eine Move-Operation auszuführen ist, und anhand der Eigenart des Argumentes (move-Kandidat oder nicht: d.h. lvalue oder rvalue) Funktionen zu überladen.Für die wichtigsten Hintergründe kann man sich die ursprünglichen Vorschlähge für die Standarderweiterungen anschauen:
A Proposal to Add Move Semantics Support to the C++ Language
A Proposal to Add an Rvalue Reference to the C++ Language
Wobei ich darauf hinweise, dass es bis zur finalen Form noch erhebliche Änderungen gegeben hat. Spätere paper befassen sich allerdings nicht mehr mit dem Warum.