Objeke referenzen gebrauch, wie object copy vermeiden?
-
ok, verstehe, ich kann auch ein alias (const referenz) benutzen:
private: std::string n; const A & a;
damit fällt das kopieren weg
-
@patrickm123 sagte in Objeke referenzen gebrauch, wie object copy vermeiden?:
O o = e_v[i]->getO();
Auch wenn getO eine const ref zurückgibt, kopierst du hier in die Variable o. Du müsstest das const& mitschleppen, also
const O& o = e_v[i]->getO();
.Und was auch ein Problem bei deinem Code ist: du hast ein
vector<E*>
und erzeugst deine Kopien von Hand mitnew
. Dann musst du auch sicherstellen, dass du deine Objekte auch wieder mitdelete
löscht! (Oder einfach einenvector<E>
nehmen oderstd::vector<std::unique_ptr<E>>
(odervector<shared_ptr<E>>
) benutzen)
-
Um mal noch zu ergänzen was WOB gesagt hat:
Deine Klasse "S" hat keinen (selbst definierten) Konstruktor und Destruktor. Der Compiler baut dir hier automatisch jeweils einen von dieser Sorte. Der generierte Destruktor löscht zwar deinen Vector, aber da du im Vector Pointer hast, räumt der Vector quasi die Pointer weg ( 64bit ) aber nicht das Objekt auf das diese Pointer zeigen ( Größe: sizeof ( E ) ), denn dass musst du von Hand mit "delete" machen. Und daher musst du selbst einen Destruktor definieren.
Anders wäre die Lage wenn du in dem Vector nicht E* sondern E speichern würdest, also die Objekt direkt im Vector. Dann würde der auto-generierte Destruktor ausreichen um sauber aufzuräumen.
-
@patrickm123 sagte in Objeke referenzen gebrauch, wie object copy vermeiden?:
ok, verstehe, ich kann auch ein alias (const referenz) benutzen:
private: std::string n; const A & a;
damit fällt das kopieren weg
Sind dir die Konsequenzen dieser Änderung bewusst?
-
@hustbaer guter punkt, d.h. änderungen in "a" sind nicht möglich über ein o Objekt. Allerdings wenn A jetzt viel Speicher brauchen würde, würde das Kopieren wegfallen?
-
@patrickm123 das andere, wichtigere Problem ist aber auch, dass nun das o-Objekt komplett von dem a-Objekt, mit dem es erzeugt wurde, abhängt. Das heißt, wenn jemand das a ändert, ist es in deinem o auch geändert. Wenn jemand das a-Objekt löscht, ist deine o-Objekt kaputt (die Referenz ist ungültig).
-
@It0101 danke für den Hinweis mit dem Aufräumen - die pointer variante hatte ich deshalb genommen, weil ich dynamisch Objekte in S anlegen wollte, ohne Objekte zu kopieren, es ist eher eine Lernübung. In einem "richtigen" Programm würde ich wohl Memory profiling machen müssen?
-
@wob danke, interessanter Punkt, dass mit dem Löschen wäre nicht so gut.... d.h. müsste man dann schauen wie man es z.B. über tests garantieren kann, dass das Programm ein gültiges a enthält
-
nein man müsste sein programmdesign so aufstellen, dass so etwas nicht vorkommen kann..........
-
im destructor, sollte ich auf "pointer is not null" checken bevor ich delete aufrufe?
-
Nein, solltest du nicht.
delete
funktioniert auch auf Nullpointern.
-
@patrickm123 sagte in Objeke referenzen gebrauch, wie object copy vermeiden?:
im destructor, sollte ich auf "pointer is not null" checken bevor ich delete aufrufe?
Es darf nur nicht uninitialisiert sein bzw nicht "schon mal vorher deleted".
-
@patrickm123 sagte in Objeke referenzen gebrauch, wie object copy vermeiden?:
@It0101 danke für den Hinweis mit dem Aufräumen - die pointer variante hatte ich deshalb genommen, weil ich dynamisch Objekte in S anlegen wollte, ohne Objekte zu kopieren, es ist eher eine Lernübung. In einem "richtigen" Programm würde ich wohl Memory profiling machen müssen?
Du solltest nicht panische Angst vor dem Kopieren haben. Du musst dir bei deinem Design vor allem darüber klar sein, wem was gehört.
Deswegen wäre es z.B. unüblich, ein Objekt auf dem Heap ( z.B. mit new erzeugt ), dass Klasse A gehört, einer anderen Klasse B als rohen Pointer zu übergeben, die mit Klasse A rein gar nichts zu tun hat. In dem Fall wäre eine Kopie durchaus in Ordnung. Oder ein alternatives Konzept wie "shared_ptr". Aber der Fokus sollte immer auf den Besitzverhältnissen liegen. Der Besitzer einer Ressource erzeugt sie und zerstört sie im Idealfall auch wieder. Und wenn die Ressource weitergeben wird ( aus A entfernt und nach B übergeben ), dann gibt es auch dafür wieder bessere Varianten als reine Pointer. Z.B. std::unique_ptr und/oder move-Semantik.Aus meiner Sicht ist die Nutzung von reinen Pointer eine absolute Notlösung wenn alle anderen Konzepte nicht tragbar sind.
-
@It0101 sagte in Objeke referenzen gebrauch, wie object copy vermeiden?:
Aus meiner Sicht ist die Nutzung von reinen Pointer eine absolute Notlösung wenn alle anderen Konzepte nicht tragbar sind.
Das gilt für rohe besitzende pointer.
-
@Swordfish Findest du denn "geborgte" Zeiger als Membervariablen OK? Ich ehrlich gesagt kaum jemals. Das wird so schnell so unübersichtlich was die Lifetimes angeht...
-
@hustbaer Meine Ergänzung bezog sich wirklich nur auf die zitierte allgemeine Aussage. Ich kann es halt nicht mehr sehen, daß Pointer allgemein phöse sind.
-
@It0101 sagte in Objeke referenzen gebrauch, wie object copy vermeiden?:
Klasse A rein gar nichts zu tun hat. In dem Fall wäre eine Kopie durchaus in Ordnung. Oder ein alternatives Konzept wie "shared_ptr". Aber der Fokus sollte immer auf den
danke - ok wer/was mit ressourcen macht/erzeugt hilft dem verständnis. das ist auch anders als in anderen programmiersprachen, wo es nur referenzen gibt
-
@Swordfish sagte in Objeke referenzen gebrauch, wie object copy vermeiden?:
@hustbaer Meine Ergänzung bezog sich wirklich nur auf die zitierte allgemeine Aussage. Ich kann es halt nicht mehr sehen, daß Pointer allgemein phöse sind.
OK, sehe ich genau so.
Speziell wenn man doch "geborgte" Pointer hat finde ich es greislich wenn der Konstruktor dann ne Referenz nimmt (und sich dann die Adresse des Objekts merkt) - nur weil der Pointer nicht NULL sein darf. *schauder*
Weil's bei der Verwendung halt sonst immer nach "by value" Semantik aussieht und wenn das dann gelogen is dann is schnell aua.
-
@hustbaer sagte in Objeke referenzen gebrauch, wie object copy vermeiden?:
dann is schnell aua.
Noch schneller Aua:
struct foo_t; { int *value; foo(const int &value) : value{ &value } {} } // ... foo_t foo{ int{ 42 } };
hehe.
-
@Swordfish sagte in Objeke referenzen gebrauch, wie object copy vermeiden?:
@It0101 sagte in Objeke referenzen gebrauch, wie object copy vermeiden?:
Aus meiner Sicht ist die Nutzung von reinen Pointer eine absolute Notlösung wenn alle anderen Konzepte nicht tragbar sind.
Das gilt für rohe besitzende pointer.
Ich sag ja nicht, dass es generell "phöse ist". Aber in den meisten Fällen, sind eben Smart-Pointer oder sogar die Nutzung der Move-Semantik eine "elegantere" Lösung, die sowohl die Wartbarkeit verbessert als auch die Fehlerquote reduziert.
Das Herumreichen von Pointern ist natürlich im Hinblick auf die Performance nicht zu toppen, birgt aber viele Risiken. Insbesondere wenn man was hübsches mit Pointern gebaut hat und dann ein halbes Jahr später daran weiterarbeitet und nicht mehr so genau im Hinterkopf hat, wem was gehört und wer wie wann wo etwas zerstören soll oder wie es sich mit der Lifetime verhält.