Klasse mit Konstante in map einfügen
-
Hallo!
Ich habe eine Klasse mit einer Konstante die ich in eine Map einfügen will.#include <map> class A { public: A() : i(5) {} private: const int i; }; int main() { std::map<int, A> m; m[10] = A(); }
Die Fehlermeldung lautet:
Die Funktion 'operator =' ist in 'A' nicht verfügbarWarum ist das so und kann man den Fehler beheben, damit es korrekt funktioniert?
-
Hallo,
sobald eine Klasse konstante oder Referenz-Member hat, wird der copy-assignmet-Operator nicht mehr automatisch erzeugt.
In diesem Fall kannst du darauf aber verzichten, wenn du die "richtige" Version zum Einfügen in eine Map verwendest:int main() { std::map<int, A> m; m.insert(std::map<int, A>::value_type(10, A())); }
Ansonsten musst du halt den op= implementieren. Eine mögliche Implementation könnte so aussehen:
class A { public: A& operator=(const A& rhs) { return *this; } ... };
[ Dieser Beitrag wurde am 25.03.2003 um 15:39 Uhr von HumeSikkins editiert. ]
-
m.insert(std::map<int, A>::value_type(10, A()));
Ich hab das bisher mit m.insert(std::make_pair(10,A())); gelöst.
Kannst Du bitte kurz das mit value_type erläutern ?
thx
-
Ich hab das bisher mit m.insert(std::make_pair(10,A())); gelöst.
Ist auch ne schöne Möglichkeit. Hat aber seine Nachteile. Komme ich gleich drauf.
make_pair sieht so aus:template<class T, class U> pair<T, U> make_pair(const T& x, const U& y);
value_type für eine Map mit Schlüssel T und Value U so:
template <class T, class U/*...*/> class map { //... public: typedef pair<const T, U> value_type; //... };
value_type ist also ein typedef auf das für eine map passendes pair.
make_pair ist nichts weiter als eine Bequemlichkeits-Funktion. Sie liefert ein passendes std::pair für eine map ohne das man die Typen für Schlüssel und Wert explizit angeben muss.
Der Nachteil von make_pair liegt in der Form der Parameterübergabe. Die Referenzübergabe von x verhindert die bequeme Nutzung von make_pair in Verbindung mit Zeichenketten-Literalen.
Die Konvertierung eines Zeichenketten-Literals in einen Zeiger-auf-(const)-char findet bei Templateargumenten nur bei nicht-Referenzparametern statt.Hat man nun eine map<string, int> oder map<const char*, int> und ein Aufruf der Form:
map<const char*, int> m; m.insert(make_pair("Hallo", 22)); // error map<string, int> m2; m2.insert(make_pair("Hallo", 22)); // error
erhält man beim insert jeweils ein Error.
Dies liegt daran, dass "Hallo" nicht nach const char* konvertiert. Vielmehr wird T nach const char[6] hergeleitet.
Damit haben wir ein pair<const char[6], int>.
Das führt aber zu einem Fehler, da im Ctor von pair nun versucht wird dem Array eine Zeichenkette zuzuweisen.Das ist der eine Grund, warum ich make_pair selten verwende.
Der zweite Grund ist, dass durch die Verwenund von make_pair häufig unnötige Konvertierungen auftreten.
Beispiel:map<double, int> m; m.insert(make_pair(22, 10));
make_pair(22, 10) erzeugt erstmal ein pair<int, int>. Da dieses Objekt aber nicht vom Typ map<double, int>::value_type ist, kann es nicht direkt in die map eingefügt werden.
Allerdings besitzt pair einen Template-Copy-Ctor. Dieser wird hier augerufen um aus dem vorhandenen pair<int, int> ein für die map passendes pair<double, int> zu machen.
Es wird hier also ein überflüssiges pair-Objekt erzeugt.
Beim Aufruf von :
map<double, int> m; m.insert(map<double, int>::value_type(22, 10));
geschieht das nicht. Hier wird ein pair<double, int> direkt mit den beiden int-Werten initialisiert.
Naja, wie auch immer. Prinzipiell ist make_pair eine gute Sache. Ich bevorzuge nur einfach value_type
[ Dieser Beitrag wurde am 25.03.2003 um 19:24 Uhr von HumeSikkins editiert. ]
-
Vielen Dank für die erklärung, wie immer gut
thx