Warum nicht überlasten operator+=() für std::vector?
Habe ich angefangen zu lernen, C++, so dass ich nicht weiß in meinem Mangel an wissen/Erfahrung, warum etwas so scheinbar einfach um einen rookie als was ich bin, zu beschreiben, ist nicht bereits in der STL. Hinzufügen eines Vektors zu einem anderen Vektor zu können, geben Sie diese:
v1.insert(v1.end(), v2.begin(), v2.end());
Frage ich mich, ob in der realen Welt Menschen, die einfach nur die überlastung der + = - operator, um diese weniger ausführlich, zum Beispiel, um die Wirkung von
template <typename T>
void operator+=(std::vector<T> &v1, const std::vector<T> &v2) {
v1.insert(v1.end(), v2.begin(), v2.end());
}
so, dann können Sie
v1 += v2;
Ich habe auch dieses set up für push_back zu "+=" ein element an das Ende. Gibt es irgendein Grund, diese Dinge nicht getan werden sollte oder sind speziell von Personen vermieden, die kompetent in C++?
- Ich würde vermuten, es ist nicht der standard, weil es ist ein bisschen umständlich - so, wie Sie es getan habe, den Wert-Typen der Vektoren muss auch identisch sein, wobei eigentlich könnte man Anhängen, beliebigen container (oder-Bereich) jeder Art, Cabrio zu den Wert-Typ der auf der LHS. Und das ist, was
insert
bereits. Auch gibt es zwei plausible Bedeutungen für die addition von Vektoren - Verkettung, wie Sie hier getan haben, oder paarweise neben wievalarray
hat, erfordern Operanden von gleicher Größe. So ist es nicht ein Idealer Kandidat für den operator zu überladen. - Nicht zu erwähnen, dass aus dem Titel bin ich davon ausgegangen, du meintest zu führen
v[i] += v[i]
über alle Elemente. - Operator-überladung sinnvoll ist, im gleichen bestimmten Fällen, aber Häufig führt es zu Verhalten, dass Menschen überraschend finden. Verhaltensweisen, die offensichtlich scheinen zu einer scheinbar nicht so zum anderen. Persönlich, ich dachte, ich Anhängen, wenn ich sah, den Titel in Frage, und das ist, weil ich in der Regel mit Python, nicht C++.
- IMHO ein Grund nicht denken
operator+=()
als pairwise addition ist, weil der Zweck ein Vektor ist, um Elemente enthalten. Bedienung der Elemente ist, was ich denken würde, über das design/die Verantwortung des Vektors. Basierend auf dieser dann nach dem Prinzip der geringsten Rechteoperator+=()
sollte davon ausgegangen werden, Vektor einfügen. - Offensichtlich hast du noch nie benutzt MatLab (oder octave).
- Ich denke, dass ist schon ein unfairer Vergleich; trotz der Bezeichnungen der Datentypen
vector
ist eine grundlegend andere Datentyp in C++ als Octave oder Matlab -- die ehemaligen implementiert die informatik definition von 'Vektor' (ein eindimensionales array), während die letztere implementieren die algebraische definition von "vector" (a one-dimensional matrix). Denn Sie sind grundlegend anders, Sie erwarten sollte, sich anders zu Verhalten und anders genutzt werden. - Wo glaubst du, informatik bekam das Wort Vektor aus in den ersten Platz? Es gibt keinen grundlegenden Unterschied. In der Tat, in MatLab ein string ist ein Vektor der element-Typ
char
. In vielerlei Hinsicht ist informatik algebra. - Der grundlegende Unterschied ist, wie man verwendet in der Regel einen Vektor in diesen beiden Domänen. Der Ursprung des Wortes ist irrelevant.
- Sie glaube nicht, dass jemand verwendet C++ für die Berechnung, Speicherung von numerischen Daten in z.B. eine
vector<complex<double>>
? - Sicher, aber Sie sind die Minderheit im Vergleich zum rest von C++ - Benutzer.
- Und jeder einzelne MatLab-Programmierer fällt in diese Minderheit (wenn Sie die C++ überhaupt). Was direkt impliziert mein Erster Kommentar.
- Und jeder einzelne Matlab-Programmierer, kümmert sich um performance, weiß nicht verwenden
std::vector
. Das ist wirklich eine sinnlose Diskussion. - Ich benutze Matlab für mehr als 60% meiner Arbeit. Ich nehme an, einer der Gründe, warum ich nicht stolpern, + = als pairwise element ist darüber hinaus, denn ich bin nicht mit Vektor für numerische Daten, sondern speichern Sie eine Liste von Objekten, die nicht Hinzugefügt werden können, zusammen. Wenn ich ging, um einen container darstellt numerische Elemente würde ich wahrscheinlich eine Art von matrix-Bibliothek. Allerdings verstehe ich jetzt, dass wenn Sie etwas, das wie
vector<double> v1, v2;
und späterv1 += v2;
es könnte zweideutig. - Dann würden Sie sicherlich erwarten, dass
v1 + v2
durchführen paarweisen addition und geben Sie einen neuen Vektor, richtig?+=
soll mit+
, aber die Zugabe im Ort. - 5 Jahre später... Dies ist ein Beispiel von "heben". Sie möchten, heben Sie die ( + ) - operator in den vector-container. Es ist eine sehr schöne Sache zu tun zu können. In Haskell, zipwith würde die Funktion, die Sie suchen. Es dauert zwei Listen und Reißverschlüsse zusammen mit einer Funktion. Man könnte auch schreiben zipwith in C++.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist tatsächlich ein Fall, wo ich möchte, um zu sehen, diese Funktionalität in form von einer überlastung der
append()
.operator+=
ist ein bisschen zweideutig, meinst du das hinzufügen der Elemente jedes Vektors zu einander? Oder meinst du Anhängen?Jedoch, wie ich schon sagte, ich würde begrüßt haben:
v1.append(v2);
Es ist klar und einfach, ich weiß nicht, warum er nicht da ist.template <typename L, typename R> void append(L& lhs, R const& rhs) { lhs.insert(lhs.end(), rhs.begin(), rhs.end()); }
(mit ein bisschen SFINAE zu beschränken L-und R-Behälter).const R& lhs
stattR const& rhs
?T const*
ist, dieconst
gilt, was ist, bevor es (hier), also besser vereinbar sein!append(a,b)
, nichta.append(b)
, richtig?Ich denke, der Hauptgrund ist, dass die Semantik von
+=
sind nicht offensichtlich. Es ist die Bedeutung, die Sie hier haben, aber es gibt auch eine gleichermaßen gültige Bedeutung, die element-Weise addition jedes element gleich große Vektoren. Durch diese Unklarheit, ich nehme an, Sie beschlossen, es sei besser, sich auf den Benutzer zu rufeninsert
wurden direkt.insert()
ist weitaus mächtiger als es arbeitet auf Iteratoren. Warum würde Sie sonst noch etwas, das weniger nützlich?Sollten Operatoren überladen werden, nur, wenn Sie nicht die änderung der Bedeutung dieser Operatoren.*
Was das bedeutet, ist, zum Beispiel, wenn es gibt keine mathematische definition des Produktes zweier Objekte, nicht überlasten die Multiplikation operator für diese Objekte. Wenn es eine mathematische Korrespondenz, Operatoren überladen kann eine Klasse mehr bequem zu bedienen, indem Sie Gleichungen ausgedrückt werden in der form a*b + c anstatt auf die ausführliche (ein.multiply(b)).add(c), Wobei die addition und die Multiplikation von Operatoren verwendet werden, die addition und die Multiplikation werden sollte, die Absicht. Jede andere Bedeutung ist mehr als wahrscheinlich, verwirren andere. Einige andere Arten, wo das überladen von Operatoren ist akzeptabel (und, meiner Meinung nach, vorzuziehen) sind intelligente Zeiger, Iteratoren, komplexe zahlen, Vektoren, und bignums.
Dies folgt aus einer der design-Ziele von C++, dass es möglich sein sollte, zu definieren-Klassen, die sind so einfach zu verwenden wie die integrierten Datentypen. Natürlich gibt es Operatoren, die Sie definieren können, auf welche Klassen sind nicht mathematische Begriffe entweder. Möchten Sie vielleicht, um eine überlastung der == und != Betreiber anstelle des Schreibens einen isEqual-Methode, und vielleicht zu überladen = da der compiler den default-Zuweisungsoperator ist nicht, was Sie wollen.
Auf der anderen Seite, das überladen eines operators zu tun, etwas unerwartetes, wie definieren ^, um eine Zeichenfolge übersetzen, japanische, ist unverständlich und gefährlich. Ihre Kolleginnen und Programmierer wird nicht glücklich sein, um herauszufinden, dass, was aussah wie eine exklusiv-oder-Vergleich war wirklich etwas ganz anderes. Die Lösung ist dann zu schreiben Sie Ihre Klassen, um es einfach zu schreiben klar und wartbar code, ob das bedeutet, dass mithilfe von operator überladen oder zu vermeiden.
Addieren von zwei Vektoren ist zu vieldeutig, um Gewähr für die Definition eines Betreibers. Wie andere gezeigt haben, viele Menschen haben unterschiedliche Vorstellungen, was dies bedeutet, in der Erwägung, dass für einen string, es wird allgemein verstanden, dass das hinzufügen von zwei strings zusammen bedeutet Verkettung. In deinem Beispiel, es ist nicht ganz klar, ob man eine Komponente Weise hinzufügen, die auf alle Elemente, füge ein element an das Ende, oder concat zwei Vektoren zusammen. Obwohl es vielleicht übersichtlicher es so zu tun, mithilfe von operator überladen um erstellen Sie Ihre eigene Programmiersprache ist nicht der beste Weg zu gehen.
*Ja, ich weiß, Stroustrup überlastet << und >> zu tun stream-Operationen eher als bitshifts. Aber diese waren nicht so Häufig genutzt wird im Vergleich zu arithmetischen und Zeiger Operatoren in den ersten Platz, und es könnte argumentiert werden, dass nun jeder weiß, wie cout, es wird allgemein davon ausgegangen, dass << und >> sind die inserter and extractor Betreiber. (Er ursprünglich versucht, einfach < und > für Eingabe und Ausgabe, aber die Bedeutung dieser Operatoren, war so tief verwurzelt in jedermanns Köpfen, dass der code nicht lesbar war.)
Zusätzlich zu dem, was andere erwähnt, über diese syntax nicht intuitiv und daher fehleranfällig ist, geht es auch gegen ein gutes design rule making Allgemeine algorithmen angewendet, um verschiedene Behälter, Kostenlose Funktionen, und die container-spezifischen algorithmen-member-Funktionen. Die meisten Container diese Regel befolgen, außer
std::string
, bekam eine Menge flack von Herb Sutter für seine monolithischen design.