std::vector<foo> erwartet ein Standart- Konstuktor der Klasse foo?
-
LordJaxom schrieb:
wiesoweshalbwarum schrieb:
es kompiliert sowohl mit gcc-3.4.5 (mingw), als auch mit vc-7.1 (beide von code::blocks gesteuert) wunderbar.
Dann benutz mal push_back.
Hint: Templatecode wird erst erzeugt, wenn er benutzt wird. Solange Du die Teile von vector, die einen Fehler erzeugen würden, garnicht benutzt, ist alles gut.
funktionuckelt! es muss nur der zuweisungsoperator definiert werden
#include <vector> #include <iostream> using namespace std; class foo { public: foo(int &bar) :m_bar(bar) { } foo(const foo &anderesFoo) :m_bar(anderesFoo.m_bar) { } foo &operator=(const foo &anderesFoo) { m_bar = anderesFoo.m_bar; return *this; } private: int &m_bar; }; int main() { int a = 3; vector<foo> test; test.push_back(foo(a)); cout << test.size() << endl; }
-
wiesoweshalbwarum schrieb:
foo &operator=(const foo &anderesFoo) { m_bar = anderesFoo.m_bar; return *this; }Ich hoffe, dir ist klar, dass hier nicht die Referenz "umgebogen" wird, sondern das Objekt, auf das anderesFoo.m_bar verweist, dem Objekt zugewiesen wird, auf das this->m_bar verweist.
-
MFK schrieb:
Ich hoffe, dir ist klar, dass hier nicht die Referenz "umgebogen" wird, sondern das Objekt, auf das anderesFoo.m_bar verweist, dem Objekt zugewiesen wird, auf das this->m_bar verweist.
ja, man kann referenzen nicht umbiegen, oder?
-
wiesoweshalbwarum schrieb:
MFK schrieb:
Ich hoffe, dir ist klar, dass hier nicht die Referenz "umgebogen" wird, sondern das Objekt, auf das anderesFoo.m_bar verweist, dem Objekt zugewiesen wird, auf das this->m_bar verweist.
ja, man kann referenzen nicht umbiegen, oder?
Eben. Und genau DA liegt ja das Problem, über das wir hier reden: Der OP möchte eine Instanzen Objekte einer Klasse mit (gültiger) Referenz per vector verwalten, was bedeutet: KEIN Copy-Ctor, KEIN operator=(), KEIN Def-Ctor.
Mit dem ("kaputten") operator=() umgehst DU zwar den push_back()-Fall, aber spätestens bei
vector<foo> test(10);wird auch der Def-Ctor gebraucht.
MFK schrieb:
wiesoweshalbwarum schrieb:
foo &operator=(const foo &anderesFoo) { m_bar = anderesFoo.m_bar; return *this; }Ich hoffe, dir ist klar, dass hier nicht die Referenz "umgebogen" wird, sondern das Objekt, auf das anderesFoo.m_bar verweist, dem Objekt zugewiesen wird, auf das this->m_bar verweist.
Global gesprochen: Wenn m_bar definiert ist als
T& m_bar;dann wird im obigen Code operator=() für T aufgerufen ... der kann alles Mögliche machen, aber er wird niemals m_bar auf ein anderes Objekt zeigen lassen (was hier gewünscht wäre).
(Dass MFK das weiß, ist mir klar, aber es soll auch wiesoweshalbwarum klar werden)Gruß,
Simon2.
-
Simon2 schrieb:
wiesoweshalbwarum schrieb:
MFK schrieb:
Ich hoffe, dir ist klar, dass hier nicht die Referenz "umgebogen" wird, sondern das Objekt, auf das anderesFoo.m_bar verweist, dem Objekt zugewiesen wird, auf das this->m_bar verweist.
ja, man kann referenzen nicht umbiegen, oder?
Eben. Und genau DA liegt ja das Problem, über das wir hier reden
aha
Little Progger schrieb:
dis kann ich leider nich übersetzen, weil für die std::vector elemente ein stan**** konstruktor vorhanden sein muss...
und ich depp dachte, der op meinte damit, ein vector würde einen standard konstruktor vorraussetzen, was definitiv nicht stimmt, weil lediglich ein zuweisungsoperator benötigt wird .

naja, nix für ungut. ich depp konnte einfach nicht herauslesen, dass das dem op klar ist.
vielleicht ist es ja auch hinter den sternchen versteckt, dass der op gar nicht von der vorraussetzung eines standard konstruktors spricht
-
Simon2 schrieb:
(Dass MFK das weiß, ist mir klar, aber es soll auch wiesoweshalbwarum klar werden)
das ist mir schon klar. damit sich m_bar nach einer zuweisung auf ein anderes objekt beziehen kann, muss es in foo intern als zeiger verwaltet werden, und dabei hat man es weder mit dynamischer speicherverwaltung zu tun, noch ist man zu einem standard konstruktor gezwungen.
#include <vector> #include <iostream> using namespace std; typedef int bar_type; class foo { public: foo(bar_type &bar) :m_bar(&bar) { } foo(const foo &anderesFoo) :m_bar(anderesFoo.m_bar) { } foo &operator=(const foo &anderesFoo) { m_bar = anderesFoo.m_bar; return *this; } const bar_type &getBar() const { return *m_bar; } const void setBar(bar_type &bar) { m_bar = &bar; } private: bar_type *m_bar; }; int main() { bar_type defaultBar = 0; vector<foo> test(3, defaultBar); cout << test.size() << endl; }
-
das const bei const void setBar kann natürlich weg. immer diese doofen copy&paste fehler

-
wiesoweshalbwarum schrieb:
das const bei const void setBar kann natürlich weg. immer diese doofen copy&paste fehler

muss nicht, ist bloß seltsam. Die Deklaration von Copy-ctor und copy-Zuweisung kann man sich auch noch sparen.
const bei Funktionsrückgabetypen ist ohnehin seltsam. Für
const T foo()
hat bei skalaren Typen T und void der Ausdruck foo() den Typ T - trotzdem bleibt das const Teil des Funktionstyps während es bei Funktionsparametern entfällt.
-
Mal eine ganz andere Frage... Ich erinnere mich daran eine vector-implementierung (glaube von Herb Sutter*) gesehen zu haben die ohne Standardkonstruktor auskommt.
Ist im Standard definiert, das wenn man eine Größenangabe dem Vektor mitgibt wirklich diese Anzahl an Elementen angelegt werden (Erinnere mich aus dieser Implementierung an ein Verfahren mit Speicherbereichsallozierungen und replace-new), oder nur das der Platz für diese vorgesehen ist?
cu André
(* War wenn ich richtig liege in einen Buch aus der Exceptional-Reihe; Werde nur meine Umzugskartons erst wieder Ende Juli öffnen).
-
Ist im Standard definiert, das wenn man eine Größenangabe dem Vektor mitgibt wirklich diese Anzahl an Elementen angelegt werden
Ja. Der Standardkonstruktor des Elements tritt bei vector nur als Defaultargument auf - es geht also keine Funktionaltität von vector verloren, wenn das Element keinen solchen Konstruktor hat. Man kann dann eben nur nicht die Funktionen mit dem entsprechenden Defaultargument verwenden.
-
fazit:
wenn es keinen standardkonstruktor gibt, kann man bei bedarf einfach ein kopierbares "standard-objekt" bei vector verwenden:#include <vector> #include <iostream> using namespace std; typedef int bar_type; class foo { public: foo(bar_type &bar) :m_bar(&bar) {} const bar_type &getBar() const { return *m_bar; } void setBar(bar_type &bar) { m_bar = &bar; } private: bar_type *m_bar; }; int main() { bar_type b1 = 0; foo defaultFoo(b1); vector<foo> test(2, defaultFoo); bar_type b2; test[1] = b2; b2 = 3; cout << test[0].getBar() << endl; cout << test[1].getBar() << endl; }
-
wiesoweshalbwarum schrieb:
...
und ich depp dachte, der op meinte damit, ein vector würde einen standard konstruktor vorraussetzen, was definitiv nicht stimmt, weil lediglich ein zuweisungsoperator benötigt wird ...Selbst das stimmt ja nicht, solange er es sich verkneift, den vector zu füllen. :p
Ich bin halt davon ausgegangen, dass der OP die ganze Funktionialität von vector nutzen können möchte - hielt ich jetzt für naheliegender als die Beschränkung auf push_back() mit einem kaputten operator=().
wiesoweshalbwarum schrieb:
...das ist mir schon klar. ...
dann ist ja gut. Aber Du wirst vermutlich zugeben, dass ich unmöglich ahnen kann, was Du weißt und was nicht.
wiesoweshalbwarum schrieb:
...damit sich m_bar nach einer zuweisung auf ein anderes objekt beziehen kann, muss es in foo intern als zeiger verwaltet werden,...
... was ja der Eingangsvorschlag des OPs war und seine Frage war, ob es noch Alternativen gäbe.
Gruß,
Simon2.
-
Simon2 schrieb:
wiesoweshalbwarum schrieb:
...damit sich m_bar nach einer zuweisung auf ein anderes objekt beziehen kann, muss es in foo intern als zeiger verwaltet werden,...
... was ja der Eingangsvorschlag des OPs war und seine Frage war, ob es noch Alternativen gäbe.
das ziel schien ein standardkonstruktor zu sein. dementsprechend wäre es eine alternative, auf einen standardkonstruktor zu verziechten und die schnittstelle von foo so zu lassen, wie sie ist.