[..]
> > Nun, es ist soweit klar, dass Tollertyp ein nicht-kopierbarer
> > Typ ist, mir ist daher unklar, warum du ihn dann kopieren
> > willst?
>
> Der konkrete Datentyp der wininet.dll kann jeweils einen Eintrag des
> Windows IE-Caches aufnehmen. Man könnte abstrahieren und sagen, der
> Datentyp ist ein Datei-Iterator. Wenn ich etwas verändern will, aber
> nach dem Test der Auswirkung das original wiederherstellen möchte,
> dann muss ich eben ein Backup machen. Da es leider nicht möglich ist
> die Anzahl der Elemente in der Datei zu ermitteln ohne sie durchlaufen
> zu sein, wollte ich das mehrfach durchlaufen der Datei ersparen ...
>
> Dein Begriff "nicht-kopierbarer Typ" ist dann wohl etwas zu hart.
Nicht wirklich. Der Datentyp, so wie er definiert ist, ist nicht
kopierbar. Das heisst nicht, dass man ihn nicht kopieren könnte,
wenn man das wollte. Du würdest dann eine Hüllklasse schreiben,
die Tollertyp enthält und dann würdest du den Kopierkonstruktor
und Zuweisungsoperator der Hüllklasse so schreiben dass das
Tollertyp-Element "richtig" kopiert wird.
struct Wrapper {
TollerTyp data;
Wrapper(const Wrapper&); // Zu definieren
Wrapper& operator=(const Wrapper&); // Zu definieren
~Wrapper(); // Zu definieren
};
[Nach der üblichen Faustregel muss dein Destruktor auch
definiert werden, wenn die Kopieroperationen zu definieren
sind. Dies scheint hier zuzutreffen, da diese Operationen
nach deiner unten folgenden Beschreibung ja Speicher
anfordern, der wieder freizugeben ist]
Technisch also kein Problem, aber es stellt sich die Frage,
ob man das wirklich will.
Schliesslich *muss* man ja Objekte eines solchen Typs nicht
unbedingt kopieren, nur weil man es technisch machen kann.
Mein Vorschlag war ein Objekt-Identitätsbezogene Lösung,
daher habe ich den Vorschlag gemacht, keine Kopien zu
erzeugen. Aus deiner bisherigen Beschreibung ist auch nicht
klar geworden, dass Kopieren eine Anforderung ist. Verwaltung
in einem Container geht - wie gezeigt - ja auch über Zeiger
oder "intelligente Zeiger".
> Für eine statische Kopie eines Puffers bin ich fündig geworden.
> Aber für "versteckte" Verschiebungen im Speicherplatz, wie bei
> std::vector möglich, funktioniert das folgende nicht:
>
> ************************
> Copy&Paste vom Seitenende der URLhttp://
msdn.microsoft.com/en-us/library/windows/desktop/aa383928%28v=...
>
> If a pointer member is not NULL, it points to the memory area
> immediately after the structure. While copying the buffer returned by a
> function into another buffer, the pointer members should be fixed to
> point to the appropriate place in the new buffer, as the following
> example shows.
>
> lpDstCEInfo->lpszSourceUrlName =
> (LPINTERNET_CACHE_ENTRY_INFO) ((LPBYTE) lpSrcCEInfo +
> ((DWORD)(lpOldCEInfo->lpszSourceUrlName) - (DWORD)lpOldCEInfo));
>
> ************************
Wie gesagt, wenn du unbedingt willst, kannst du eine Hüllklasse
von TollerTyp definieren und die Kopieroperationen wie oben gezeigt
definieren. Start wie oben.
> Abgesehen von den MS Datentypen ist das, wenn ich es richtig
> interpretiere, folgende Rechnung:
>
> PointerTollerTyp buffer1 = (PointerTollerTyp) new char[buffer_size];
>
> buffer1 sei befüllt worden
>
> PointerTollerTyp buffer2 = (PointerTollerTyp) new char[buffer1->StructSize];
>
> Nun memcopy oder das Ding als char-Array in Schleife Zeichenweise kopieren.
>
> Fehlt nur noch die Pointeranpassung am Beispiel-Pseudocode:
>
> offset = buffer1->NullTerminatedCString1 - buffer1
> //sollte den Adressversatz geben
>
> buffer2->NullTerminatedCString1 = buffer2 + offset
> //sollte den Zeiger NullTerminatedCString1
> //auf die nun korrekte Adresse verweisen lassen
>
> Oder?
Hört sich so an, ja (Habe mir das aber nicht im Detail angeguckt).
> Vielleicht ist std::vector doch nicht direkt geeignet,
> zumindest nicht für std::vector<TollerTyp> oder
> besser andersherum: TollerTyp ist nicht für std::vector
> geeignet :-)
Wie gesagt, es hängt von deinen Anforderungen ab.
Container können auch Pointer enthalten, da ist erstmal
nichts gegen zu sagen. Problematisch würde es, wenn du
den Container dann kopieren willst. Dann nimmst du besser
einen Container mit SmartPointer oder du nimmst die
oben beschriebene TollerType-Hüllklasse.
> > Ansatz (b) hat den Vorteil, dass du unterschiedliche Lebensdauern
> > von TollerTyp abbilden kannst, da du eine eigene Löschfunktion
> > angeben kannst beim Erzeugen dieses SmartPointers.
>
> hört sich interessant an. Aber die Korrektur über Zeigerarithmetik,
> müsste auch bei einem std::vector<boost::shared_pointer<TollerTyp>>
> für die jeweiligen char* Elemente in TollerTyp gemacht werden.
Nein, da beim Kopieren eines boost::shared_pointer<TollerTyp> die
Daten nicht kopieren werden, sondern nur die Referenzen. das ist
wie bei normalen Zeigern, nur brauchst du dich nicht um die
Speicherverwaltung zu kümmern.
> Zumindest könnte ich so einen shared_pointer nicht an eine C Funktion
> übergeben. Zumindest hab ich auf den schnellen Blick bei Boost nichts
> derartiges gesehen.
Brauchst du ja auch nicht. Du kannst vom boost::shared_ptr
per Funktion "get" an das Objekt drankommen.
Viel Erfolg noch und besten Gruss aus Bremen,
Daniel