 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Dirk Clemens Guest
|
Posted: Tue Sep 02, 2003 11:30 am Post subject: Re: §18.4.1.3 [lib.new.delete.placement] - Wie rufe ich den |
|
|
Bodo Thiesen wrote:
| Quote: | class X {
private:
X(const class X & x) {}
X & operator = (const class X & x) {}
|
Hallo Bodo,
ein wenig abweichend von deiner Fragestellung:
Ich nehme an, dass du den Aufruf von der beiden Funktionen unterbinden willst und sie daher als private declariert hast.
Das Problem ist nur, das class-members oder friend's immer noch darauf zugreifen können.
Versuche doch mal ...
class X {
private:
X(const class X & x); // <-- anstatt '{}' --> ';'
X & operator = (const class X & x); // <-- anstatt '{}' --> ';'
.... ohne die Funktionen irgendwo zu definieren. Dann meckert der Linker als letzte Istanz die missbräuchliche Verwendung
der beiden Funktionen an.
So mache ich es immer ;-)
Lemmi
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Markus Schaaf Guest
|
Posted: Tue Sep 02, 2003 12:54 pm Post subject: Re: §18.4.1.3 [lib.new.delete.placement] - Wie rufe ich den |
|
|
"Bodo Thiesen" <bothie (AT) gmx (DOT) de> schrieb:
| Quote: | void * operator new(std::size_t size, void * ptr) throw();
void * operator new[](std::size_t size, void * ptr) throw();
void operator delete(void * ptr, void *) throw();
void operator delete[](void * ptr, void *) throw();
aufgefallen. Zum ersten hat der Standard auch gleich ein Beispiel parat,
wie er aufzurufen ist, insbesondere für die delete Varianten gibt es aber
exakt kein Beispiel.
|
Wofür?
| Quote: | Meine Experimente haben kein Erfolg gezeigt, ich poste
jetzt mal einfach mein Testquelltext (der ein unsauberen Workaround
benutzt), den vielleicht jemand korrigieren könnte, der die Placements
schonmal benutzt hat. (Es geht hier nur um den delete Operator, der Rest
scheint korrekt zu funktionieren.)
|
Was ist die Frage?
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Bodo Thiesen Guest
|
Posted: Tue Sep 02, 2003 1:46 pm Post subject: Re: §18.4.1.3 [lib.new.delete.placement] - Wie rufe ich den |
|
|
Markus Schaaf schrieb:
| Quote: | "Bodo Thiesen" <bothie (AT) gmx (DOT) de> schrieb:
void * operator new(std::size_t size, void * ptr) throw();
void * operator new[](std::size_t size, void * ptr) throw();
void operator delete(void * ptr, void *) throw();
void operator delete[](void * ptr, void *) throw();
aufgefallen. Zum ersten hat der Standard auch gleich ein Beispiel parat,
wie er aufzurufen ist, insbesondere für die delete Varianten gibt es aber
exakt kein Beispiel.
Wofür?
|
Also ich war jetzt grade in der Versuchung, diesen Artikel nach desd zu
x-posten, habe es dann aber doch sein gelassen. Gut, lesen wir uns mal den
Satz gemeinsam durch: "Zum ersten [Operator] hat der Standard auch gleich
ein Beispiel parat, wie er aufzurufen ist, [...]". Fassen wir zusammen. Es
geht um ein Beispiel, welches im Standard steht, und zeigt, wie *dieser*
Operator new aufgerufen wird. Soweit mitgekommen? Ok, dann weiter: "[...]
insbesondere für die delete Varianten gibt es aber exakt kein Beispiel."
Zur Erinnerung: Es ging um ein Beispiel im Standard für den Aufruf des
new-Operators. Also geht es hier wohl darum, daß ein Beispiel für den
Aufruf des delete Operators "fehlt". Jetzt klar? Wenn nicht, sollten wir
uns wirklich in desd treffen ...
| Quote: | Meine Experimente haben kein Erfolg gezeigt, ich poste
jetzt mal einfach mein Testquelltext (der ein unsauberen Workaround
benutzt), den vielleicht jemand korrigieren könnte, der die Placements
schonmal benutzt hat. (Es geht hier nur um den delete Operator, der Rest
scheint korrekt zu funktionieren.)
Was ist die Frage?
|
WIE WIRD DER VERDAMMTE delete OPERATOR AUFGERUFEN!
Oder anders ausgedrückt: Aus drei mach eins: Wie lautet der Ersatzausdruck,
für dieses Wirrwarr:
T * tmp=(T*)new space;
memcpy(tmp,ptr+i,sizeof(T));
delete tmp;
Letztlich geht es darum, den Destruktor ~T() für die Instanz an der Adresse
ptr+i aufzurufen, ohne den Speicherbereich freizugeben. (Das Gegenstück zu
dem new Operator halt, der nur den Konstruktor aufruft, ohne Speicher zu
belegen.)
Gruß, Bodo
--
Wer fragt ist nur drei Minuten Dumm.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
C. Gerald Knizia Guest
|
Posted: Tue Sep 02, 2003 1:57 pm Post subject: Re: §18.4.1.3 [lib.new.delete.placement] - Wie rufe ich den |
|
|
Bodo Thiesen schrieb:
| Quote: | Letztlich geht es darum, den Destruktor ~T() für die Instanz an der
Adresse ptr+i aufzurufen, ohne den Speicherbereich freizugeben.
|
spricht etwas gegen:
reinterpret_cast< T* >( ptr + i )->~T();
?.
--
- C. Gerald Knizia/cgk | #28673212 | this post was made with intention
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Markus Schaaf Guest
|
Posted: Tue Sep 02, 2003 2:02 pm Post subject: Re: §18.4.1.3 [lib.new.delete.placement] - Wie rufe ich den |
|
|
"C. Gerald Knizia" <cgk.d (AT) gmx (DOT) net> schrieb:
| Quote: | spricht etwas gegen:
reinterpret_cast< T* >( ptr + i )->~T();
|
Ja. Was soll der »reinterpret_cast«?
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
C. Gerald Knizia Guest
|
Posted: Tue Sep 02, 2003 2:16 pm Post subject: Re: §18.4.1.3 [lib.new.delete.placement] - Wie rufe ich den |
|
|
Markus Schaaf schrieb:
| Quote: | "C. Gerald Knizia" <cgk.d (AT) gmx (DOT) net> schrieb:
spricht etwas gegen:
reinterpret_cast< T* >( ptr + i )->~T();
Ja. Was soll der »reinterpret_cast«?
|
Das soll dafür sorgen, dass der Destruktor von T aufgerufen wird und nicht
der von dem, was auch immer "ptr+i" ist (Es könnte z.B. auch char* o.ä.
sein). Wenn ptr+i selbst schon den Typ von T hat, dann ist der cast
natürlich nicht nötig.
--
- C. Gerald Knizia/cgk | #28673212 | this post was made with intention
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Bodo Thiesen Guest
|
Posted: Tue Sep 02, 2003 7:00 pm Post subject: Re: §18.4.1.3 [lib.new.delete.placement] - Wie rufe ich den |
|
|
Falk Tannhäuser schrieb:
| Quote: | Bodo Thiesen wrote:
§18.4.1.3 [lib.new.delete.placement]
In den Absätzen 8 bzw. 10 steht dort:
Notes: Default function called when any part of the initialization in a
placement new expression that invokes the library’s nonarray [bzw.
array] placement operator new terminates by throwing an exception
(5.3.4).
|
Ok, jetzt nachdem ich mir den Satz weitere drei mal durchgelesen habe,
scheine ich ihn dann auch endlich verstanden zu haben ...
| Quote: | using namespace std; // Damit der Rest kompiliert...
|
Wenn gcc das mal auch wüsste ...
(ok, ist aber nur eine Testcode gewesen, daher nicht ganz so wichtig.)
| Quote: | X(const class X & x) {}
X & operator = (const class X & x) {}
Diese Beiden brauchen, da sie nicht benutzt werden sollen, nur deklariert,
aber nicht definiert zu werden, d.h. ';' an Stelle von ' {}'. Dies
vermeidet auch die Warnung, dass operator= nichts zurückgibt.
|
Jo, den Tipp hat mir Dirk aber auch schon gegeben.
| Quote: | typedef char space[sizeof(T)];
Solche typedefs sind m.E. grässlich hässlich, da sie mehr Verwirrung
stiften (s.u.) als sie die Lesbarkeit des Programms erhöhen.
|
Nun ja, sehe ich anders. YMMV ;-)
Aber mit dem s.u. hast Du auch wieder recht. Ich hätte aber auch ein
typedef struct { char x[sizeof(T)] } space; konstruieren können, dann wäre
dieses Problem gelöst (hey, und ohne weitere Code-Änderungen ...).
| Quote: | void Resize(size_t new_size) {
new_ptr=(T*)realloc((void*)ptr,sizeof(T)*new_size);
Natürlich kann realloc deine Objekte doch kopieren
|
richtig.
| Quote: | (was du eigentlich nicht wolltest),
|
1. wie kommst Du darauf?
2. Das ist mir tatsächlich egal.
| Quote: | und zwar mittels memcpy, was nur für PODs erlaubt ist.
|
*nachschlag* The acronym POD stands for "plain old data."
Ich verstehe dies jetzt nicht, aber sehen wir erstmal weiter.
| Quote: | Weiterhin werden in diesem Fall für die Originalobjekte nicht die
Destruktoren auf- gerufen und ihr Speicherplatz trotzdem freigegeben -
nicht sehr schön... Je nachdem, was die Klasse T sonst noch so macht, kann
das inne Büx gehen...
|
Ok, zwei möglichkeiten: 1. Entweder diese Aussage stimmt so nicht, oder ich
brauche ein Beispiel.
Also: Was schief gehen muß, wäre sowas:
class X {
char buffer[1000];
char * ptr1;
char * ptr2;
char * ptr3;
X(int a,int b,int c) {
if (a+b+c>1000) throw 42;
ptr3=(ptr2=(ptr1=buffer)+a)+b
}
};
Aber wer macht sowas?
Abgesehen von solch einem Unsinn: In welcher Situation könnte es noch
knallen? (Wenn man char buffer[1000] z.B. durch char * buffer ersetzen
würde, welches dann mit new ein array zugewiesen bekommt, funzt es ja
wieder.)
Schau ich mir jetzt mal an.
| Quote: | Letzte Bemerkung: Man bevorzuge die C++-Casts (hier: static_cast) an
Stelle der C-Casts, insbesondere in Templates!
|
Jo, wenn ich denn mal so langsam die C++-Casts drauf hätte...
| Quote: | (T*)new (ptr+i)T();
Cast unnötig, da der new-Ausdruck bereits einen 'T*' zurückgibt (der hier
sowieso nicht benutzt wird).
|
Irgendwie hatte ich mit diesem new ein paar auseinandersetzungen, die ich
so gelöst habe.
| Quote: | T * tmp=(T*)new space;
memcpy(tmp,ptr+i,sizeof(T));
delete tmp;
Hmmm... Hier legst du eine Kopie an (per memcpy, selber Kommentar wie
oben) und zerstörst gleich darauf die Kopie, nicht aber das Original.
|
Unter der Annahme, daß die Kopie identisch mit dem Original ist, sollte es
doch funktionieren. Z.B. könnte der Destruktor die Datei schließen, die das
Objekt geöffnet hält o.ä. Wie gesagt: Ich will ein Beispiel, in dem diese
Methode knallt.
| Quote: | Ausserdem: Da 'space' nur ein typedef für ein 'char[]'-Array ist und der
Typ des einem delete[] übergebenen Zeigers mit dem Typ des von new[]
zurückgegebenen Zeigers genau übereinstimmen muss, müsste es 'delete[]
(char*)tmp' heissen.
|
Deswegen sprach ich von einem unsauberen Workaround.
| Quote: | Daher sicher die 'Mismatched free() / delete / delete
[]'-Fehlermeldung.
|
Richtig, wenn man es so betrachtet, bekommt diese Meldung wieder einen ganz
anderen Sinn ...
| Quote: | Dies ruft dann natürlich nicht den Destruktor von T
auf... Was du hier willst, ist sicher ganz einfach 'ptr[i].~T();'.
|
Wenn ich diese Aufrufmöglichkeit gewusst hätte, hätte ich mir einiges an
Zeit gespart ... Ok, das ist dann ja wohl schon die Lösung :-P
| Quote: | printf(">>Array<X *> array;n");
Sollte sicher 'printf(">>Array<X> array;n");' heissen (ohne '*')?
|
Egal, ist eh nur eine Debug Meldung.
| Quote: | Ansonsten ist es vielleicht das einfachste, einen 'std::vector<X*>' zu
benutzen (gekapselt in einer Klasse, wobei die Resize-Methode die
entsprechenden new/delete-Aufrufe tätigt).
|
Damit ich wieder mit Zeigern arbeiten muß. Danke. Nein, meine Experimente
zielen darauf ab, weitestgehend auf Zeiger, und vor allem auf Dynamischen
Speicher zu verzichten. (Ob es praktikabel ist, wird sich später im Test
zeigen müssen...)
Ok, auf jeden Fall danke ich Dir schonmal für die Mühe, und hoffe, Du
kannst mir ein verständliches Trivialbeispiel zeigen, bei dem mein
Array-Template knallt.
Gruß, Bodo
--
Wer fragt ist nur drei Minuten Dumm.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Bodo Thiesen Guest
|
Posted: Tue Sep 02, 2003 10:24 pm Post subject: Re: §18.4.1.3 [lib.new.delete.placement] - Wie rufe ich den |
|
|
Bodo Thiesen schrieb:
| Quote: | Falk Tannhäuser schrieb:
Bodo Thiesen wrote:
new_ptr=(T*)realloc((void*)ptr,sizeof(T)*new_size);
Natürlich kann realloc deine Objekte doch kopieren
richtig.
und zwar mittels memcpy, was nur für PODs erlaubt ist.
*nachschlag* The acronym POD stands for "plain old data."
Ich verstehe dies jetzt nicht, aber sehen wir erstmal weiter.
|
Ok, jetzt verstehe ich es, jetzt, nachdem ich
Gelesen habe.
Dumm, dumm.
Ich habe es jetzt anders realisiert. Ein T * * ptr_array, welches mit
realloc vergrößert oder verkleinert wird, und jedes Element wird einzeln
via new angelegt. Ist zwar nicht gerade das, was ich wollte, aber geht wohl
nicht anders. (Ich will keine Forderungen an T stellen (außer daß es einen
public default Konstruktor und einen public Destruktor gibt), daher
funktionieren die Lösungen aus cuj-12-2001.php nicht.)
| Quote: | [...], und hoffe, Du kannst mir ein verständliches Trivialbeispiel
zeigen, bei dem mein Array-Template knallt.
|
Nicht mehr nötig.
--
Gruß, Bodo [DE: http://piology.org/ILOVEYOU-Signature-FAQ.html]
@@@@@ GEGEN TCG aka. TCPA: @@@@@ [DE: http://www.againsttcpa.com]
Wer fragt ist nur drei Minuten Dumm.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Kostka, Volkmar Guest
|
Posted: Tue Sep 02, 2003 10:34 pm Post subject: Re: §18.4.1.3 [lib.new.delete.placement] - Wie rufe ich den |
|
|
Hallo,
Bodo Thiesen wrote:
....
| Quote: | Weiterhin werden in diesem Fall für die Originalobjekte nicht die
Destruktoren auf- gerufen und ihr Speicherplatz trotzdem freigegeben -
nicht sehr schön... Je nachdem, was die Klasse T sonst noch so macht, kann
das inne Büx gehen...
Ok, zwei möglichkeiten: 1. Entweder diese Aussage stimmt so nicht, oder ich
brauche ein Beispiel.
Also: Was schief gehen muß, wäre sowas:
class X {
char buffer[1000];
char * ptr1;
char * ptr2;
char * ptr3;
X(int a,int b,int c) {
if (a+b+c>1000) throw 42;
ptr3=(ptr2=(ptr1=buffer)+a)+b
}
};
Aber wer macht sowas?
Abgesehen von solch einem Unsinn: ...
|
Wenn du zB "Clusterlisten" implementierst. Dabei werden immer N Elemente
am Stueck allokiert, aber trotzdem untereinander mit Zeigern verbunden.
Ein solches Objekt kannst du nicht per memcpy kopieren, da dann die
Zeiger falsch stehen.
Beispiel:
class ListenEintrag {
ListenEintrag * prev;
ListenEintrag * next;
....
};
class ListenCluster {
ListenEintrag m_cluster[N];
ListenCluster(const ListenCluster& prev)
{
m_cluster[0].prev = &prev.m_cluster[N-1];
prev.m_cluster[N-1].next = &m_cluster[0];
for (int i = 0; i < N-1; ++i)
{
m_cluster[i].next = &m_cluster[i+1];
m_cluster[i+1].prev = &m_cluster[i];
}
m_cluster[i].next = 0;
};
....
};
Durchaus gaengig, wenn die Anzahl der Allokation begrenzt werden soll,
oder der Speicher nur in erheblich groesseren Einheiten angefordert
werden kann.
Also kein Unsinn.
MFG
Volkmar Kostka
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Bodo Thiesen Guest
|
Posted: Wed Sep 03, 2003 3:20 pm Post subject: Re: §18.4.1.3 [lib.new.delete.placement] - Wie rufe ich den |
|
|
-> Meine folgenden Ausführungen ändern (leider) nichts daran, daß man
memcpy nicht so verwenden kann, wie ich es gerne täte ...
Kostka, Volkmar schrieb:
| Quote: | Bodo Thiesen wrote:
class X {
char buffer[1000];
char * ptr1;
char * ptr2;
char * ptr3;
X(int a,int b,int c) {
if (a+b+c>1000) throw 42;
ptr3=(ptr2=(ptr1=buffer)+a)+b
}
};
Aber wer macht sowas?
class ListenEintrag {
ListenEintrag * prev;
ListenEintrag * next;
...
};
class ListenCluster {
ListenEintrag m_cluster[N];
ListenCluster(const ListenCluster& prev)
{
m_cluster[0].prev = &prev.m_cluster[N-1];
prev.m_cluster[N-1].next = &m_cluster[0];
for (int i = 0; i < N-1; ++i)
{
m_cluster[i].next = &m_cluster[i+1];
m_cluster[i+1].prev = &m_cluster[i];
}
m_cluster[i].next = 0;
};
...
};
Durchaus gaengig, wenn die Anzahl der Allokation begrenzt werden soll,
oder der Speicher nur in erheblich groesseren Einheiten angefordert
werden kann.
|
Man müsste sich hier zwei Dinge überlegen:
1. Ist dies eine Liste oder sind es mehrere? Wenn es eine wäre, müsste eine
Instanz von ListenCluster ausreichen (wie die das löst ist zweitrangig).
Wenn es hingegen mehrere sind, sehe ich nicht ein, warum diese in dieser
Art verknüpft werden.
2. Wie wird auf die Elemente zugegriffen? And dem Konzept der Klassen
vorbei? Also man nehme ein ListenElement * und arbeitet damit, ohne zu
berücksichtigen, zu welchem ListenCluster es überhaupt gehört? Ich möchte
jetzt keinen Flame starte, daher verkneife ich mir jetzt mal eine Aussage
....
Meine Version:
class ListenEintrag {
...
};
class ListenCluster {
class ListenCluster * prev;
class ListenCluster * next;
ListenEintrag m_cluster[N];
ListenCluster(const ListenCluster * p) {
prev = p;
p.next=this;
next=NULL;
};
Ist nicht nur schneller, sondern spart auch Platz. Für den Zufriff auf die
Elemente wäre sowieso die jeweilige Instanz zuständig. Der Zugriff könnte
dann ungefähr so aussehen:
friend class ListenEintrag * Next(ListenCluster * & lc,size_t & num) {
++num;
while (num>N) {
num-=N;
(lc=lc.next) || throw ...;
}
return m_cluster+num;
}
Ach ja, und daß man daraus sinnvoller weise ein template machen würde, ist
natürlich klar ...
Letztlich löst dies mein Problem aber auch nicht, denn es sind nach wie vor
zwei Zeiger vorhanden, die ich nicht los werde...
Andererseits fürde ich auch das ganze Gedöns in der Klasse selbst
verstecken, etwa so (jetzt mal direkt als template, packe jetzt aber keine
Implementationen mehr dazu):
template <class T> class ListenCluster {
class ListenEintrag {
T entry[N];
};
std::vector<ListenEintrag*> cluster;
size_t num,free;
typedef "irgendwas" iterator;
und dann kann man damit arbeiten. Bleibt für mich noch die Frage, wozu man
sowas überhaupt braucht.
-----
Ok, Not macht erfinderisch ...
Würde die Einführung eines 'move'-Operators (der als default Variante via
memcpy implementiert würde, und auf jeden Fall Implementationsspezifischen
Unsinn berücksichtigen könnte) hier helfen? Frei nach dem Motto "jede ist
sich selbst der nächste" ...?
Für dieses Beispiel (ListenCluster) würde es reichen, aber gibt es noch
andere denkbare Fälle, in denen man damit nicht mehr weiter kommt?
(Letztlich will ich ja einer Instanz sagen: "Du wirst jetzt von X nach Y
verschoben, passe deine Referenzen entsprechend an", entsprechend dem
hier:
void operator move(TYPE * src, TYPE * dst);
Und Zeiger von außen auf dieses Objekt müssen entsprechend auch von außen
aus angepasst werden. (ptr+=dst-src oder so).
Eventuell lässt man dem move-Operator die Wahl, eine Exception zu werfen,
falls er nicht in der Lage ist, alle Referenzen anzupassen (warum?), und
könnte dann eine renew-Operation in einem try-Block durchführen, ala
try {
belege neuen Speicher
move für alle bleibenden Elemente,
Konstrukto für Neue bzw. Destruktor für Alte
Freigeben des alten Speichers
} catch (...) {
case std::move_failed:
Freigeben des neuen Speichers, und ...
case std::bad_alloc:
... pech gehabt ...
}
Dann könnte man auch endlich[TM] einen renew Operator im Standard
aufnehmen, allerdings nicht mit der Garantie, daß er immer funktionieren
muß (aber die gibt es ja für new und delete auch nicht ...).
Gruß, Bodo
--
Wer fragt ist nur drei Minuten Dumm.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Kostka, Volkmar Guest
|
Posted: Wed Sep 03, 2003 6:36 pm Post subject: Re: §18.4.1.3 [lib.new.delete.placement] - Wie rufe ich den |
|
|
Hallo,
Bodo Thiesen wrote:
| Quote: | -> Meine folgenden Ausführungen ändern (leider) nichts daran, daß man
memcpy nicht so verwenden kann, wie ich es gerne täte ...
Kostka, Volkmar schrieb:
class ListenEintrag {
ListenEintrag * prev;
ListenEintrag * next;
...
};
class ListenCluster {
ListenEintrag m_cluster[N];
ListenCluster(const ListenCluster& prev)
{
m_cluster[0].prev = &prev.m_cluster[N-1];
prev.m_cluster[N-1].next = &m_cluster[0];
for (int i = 0; i < N-1; ++i)
{
m_cluster[i].next = &m_cluster[i+1];
m_cluster[i+1].prev = &m_cluster[i];
}
m_cluster[i].next = 0;
};
...
};
Durchaus gaengig, wenn die Anzahl der Allokation begrenzt werden soll,
oder der Speicher nur in erheblich groesseren Einheiten angefordert
werden kann.
Man müsste sich hier zwei Dinge überlegen:
1. Ist dies eine Liste oder sind es mehrere? Wenn es eine wäre, müsste eine
Instanz von ListenCluster ausreichen (wie die das löst ist zweitrangig).
Wenn es hingegen mehrere sind, sehe ich nicht ein, warum diese in dieser
Art verknüpft werden.
|
Es ist eine Liste von ListenEintrag-Elementen. Aber es werden aus
verschiedenen Gruenden immer mehrere solche Elemente auf einmal
angefordert.
Die ListenCluster-Elemente werden nur dazu verwendet, um die Anforderung
mehrerer Elemente zu verwalten.
| Quote: |
2. Wie wird auf die Elemente zugegriffen? And dem Konzept der Klassen
vorbei? Also man nehme ein ListenElement * und arbeitet damit, ohne zu
berücksichtigen, zu welchem ListenCluster es überhaupt gehört? Ich möchte
jetzt keinen Flame starte, daher verkneife ich mir jetzt mal eine Aussage
...
|
Im ersten Cluster ist m_cluster[0] der Kopf der Liste, ueber die Liste
wird ganz normal ueber prev/next iteriert.
Aber lassen wir dass. Man kann immer was dafuer oder dagegen sagen.
Meiner Meinung nach hat eine Klasse, die mehr als nur PODs beinhaltet,
einen Zuweisungsoperator und einen Kopierkonstruktor zu haben.
Basta.
Klasseninstanzen werden *nicht* mit memcpy() kopiert.
MFG
Volkmar Kostka
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|