 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Marcel Müller Guest
|
Posted: Sat Feb 04, 2006 11:00 pm Post subject: Returntyp von Operator new und Arrays |
|
|
Hallo!
Kann man mit dem new-Operator eigentlich auch Arrays als logischen Typ
allozieren?
Also in C++ gibt es ja auch Array-Typen mit zur Compilezeit bekannter Größe:
typedef int my_type[5];
void foo(my_type* array); // bindet nur an int(*)[5]
Wenn ich aber new my_type schreibe, wird offenbar int* zurückgeliefert
und nicht my_type*. Die Array-Eigenschaft geht verloren.
Folglich gelingt der Aufruf der Funktion foo in der folgenden Zeile nicht:
foo(new my_type); // Fehler
// Sinngemäß: Kann int* nicht in int (*)[5] konvertieren.
Das wäre das Verhalten, wenn der new[] Operator verwendet wird, bei dem
die Größe des Arrays erst zur Laufzeit bekannt ist.
Schön und gut, aber wie Alloziere ich denn nun /ein/ Objekt von Typ int[5]?
Hintergrund: die Funktion foo ist eingetlich ein Template der Art:
template <typename T, size_t S>
void foo(T (*)[S]);
Das bietet allerlei Möglichkeiten, da die Größe des Arrays nun zur
Compilezeit bekannt ist und auch bleibt.
Natürlich kann ich jetzt eine Proxy-Klasse um den Typ herum schreiben
und allerlei Operatoren überladen, um das Problem zu umgehen. Aber
irgendwie scheint mir das abwegig und lästig.
Vor allem wird das dann ein schwer zu umgehendes Problem, wenn der
Arraytyp selbst an einen Template-Typ T2 irgendeiner Klasse bindet und
die Implementation vernünftigerweise erwartet, dass eine Funktion
foo(T2*) mit foo(new T2) aufgerufen werden kann.
Irgendwelche Ideen?
Mache ich da etwas falsch?
Hat mein Compiler (im Moment gcc 3.3.5) einen Schlag?
Marcel
--
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 |
|
 |
kanze Guest
|
Posted: Tue Feb 07, 2006 2:03 pm Post subject: Re: Returntyp von Operator new und Arrays |
|
|
Marcel Müller wrote:
| Quote: | Kann man mit dem new-Operator eigentlich auch Arrays als
logischen Typ allozieren?
|
Kann man, soll man in Allgemein aber nicht.
| Quote: | Also in C++ gibt es ja auch Array-Typen mit zur Compilezeit
bekannter Größe:
typedef int my_type[5];
void foo(my_type* array); // bindet nur an int(*)[5]
|
So weit hat's immer gegeben. Auch in C.
Vorsicht aber. Typischerweise wird so eine Funktion für zwei
dimensionnalen Arrays verwendet. So ungefähr:
my_type array[ 20 ] ;
foo( array ) ;
| Quote: | Wenn ich aber new my_type schreibe, wird offenbar int*
zurückgeliefert und nicht my_type*. Die Array-Eigenschaft geht
verloren.
|
Mehr oder weniger. C-artige Arrays sind nicht normalle Typen.
Wenn du einen allokierst, bekommst du nicht einen Zeiger auf dem
Array, sondern einen Zeiger auf seinem ersten Element. Um einen
my_type* von new zu bekommen, musst du etwas wie "new
my_type[1]" schreiben.
| Quote: | Folglich gelingt der Aufruf der Funktion foo in der folgenden
Zeile nicht:
foo(new my_type); // Fehler
// Sinngemäß: Kann int* nicht in int (*)[5] konvertieren.
Das wäre das Verhalten, wenn der new[] Operator verwendet
wird, bei dem die Größe des Arrays erst zur Laufzeit bekannt
ist.
Schön und gut, aber wie Alloziere ich denn nun /ein/ Objekt
von Typ int[5]?
|
new my_type[1]
Es geht nicht anders (auf historischen Grunden).
| Quote: | Hintergrund: die Funktion foo ist eingetlich ein Template der Art:
template <typename T, size_t S
void foo(T (*)[S]);
Das bietet allerlei Möglichkeiten, da die Größe des Arrays nun
zur Compilezeit bekannt ist und auch bleibt.
Natürlich kann ich jetzt eine Proxy-Klasse um den Typ herum
schreiben und allerlei Operatoren überladen, um das Problem zu
umgehen. Aber irgendwie scheint mir das abwegig und lästig.
|
Ich wurde std::vector statt C-artige Arrays benutzen.
| Quote: | Vor allem wird das dann ein schwer zu umgehendes Problem, wenn
der Arraytyp selbst an einen Template-Typ T2 irgendeiner
Klasse bindet und die Implementation vernünftigerweise
erwartet, dass eine Funktion foo(T2*) mit foo(new T2)
aufgerufen werden kann.
Irgendwelche Ideen?
Mache ich da etwas falsch?
|
C-artige Arrays benutzen? :-)
| Quote: | Hat mein Compiler (im Moment gcc 3.3.5) einen Schlag?
|
Nein. Die Sprache aber wohl.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
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 |
|
 |
Marcel Müller Guest
|
Posted: Sat Feb 18, 2006 10:06 pm Post subject: Re: Returntyp von Operator new und Arrays |
|
|
kanze wrote:
| Quote: | Marcel Müller wrote:
Schön und gut, aber wie Alloziere ich denn nun /ein/ Objekt
von Typ int[5]?
new my_type[1]
Es geht nicht anders (auf historischen Grunden).
|
OK, nicht schön, aber selten.
Die unangenehme Nebenwirkung ist, dass dabei immer der operator new[]
aufgerufen wird und konsequenterweise das Objekt auch mit delete[]
freigegeben werden muss.
| Quote: | Natürlich kann ich jetzt eine Proxy-Klasse um den Typ herum
schreiben und allerlei Operatoren überladen, um das Problem zu
umgehen. Aber irgendwie scheint mir das abwegig und lästig.
Ich wurde std::vector statt C-artige Arrays benutzen.
|
In diesem Fall ungern, denn dann kann ich keine Spezialisierungen für
Trivialfälle mehr machen.
Marcel
--
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 |
|
 |
Bob Hairgrove Guest
|
Posted: Sat Feb 18, 2006 11:06 pm Post subject: Re: Returntyp von Operator new und Arrays |
|
|
On Sat, 18 Feb 2006 23:03:11 +0100, Marcel Müller
<news.5.maazl (AT) spamgourmet (DOT) org> wrote:
| Quote: | In diesem Fall ungern, denn dann kann ich keine Spezialisierungen für
Trivialfälle mehr machen.
|
Was für Trivialfälle, und warum überhaupt spezialisieren?
--
Bob Hairgrove
NoSpamPlease (AT) Home (DOT) com
--
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 |
|
 |
Marcel Müller Guest
|
Posted: Sun Feb 19, 2006 11:06 am Post subject: Re: Returntyp von Operator new und Arrays |
|
|
Bob Hairgrove wrote:
| Quote: | In diesem Fall ungern, denn dann kann ich keine Spezialisierungen für
Trivialfälle mehr machen.
Was für Trivialfälle, und warum überhaupt spezialisieren?
|
Mathematisches Zeugs, wie z.B. 2*2 Matrix-Inversion (real, komplex).
Ausserdem möchte ich zur Compilezeit sicherstellen, dass bestimmten
Funktionen nur Arrays einer bestimmten Größe übergeben werden können.
Das Ganze ist natürlich im Kontext von Smart-Arrays zu sehen, die im
Wesentlichen auf boost::shared_array aufsetzen, selbige aber funktionell
deutlich erweitern. Da tritt das Problem aufgrund der zusätzlichen
Kapselung natürlich zunächst mal nicht auf. Aber es gibt Schnittstellen,
in denen die die Array-Typen nativ auftreten. Beispielsweise könnte man,
wenn die Arraygröße im Returnwert von new noch enthalten ist, eine
Template-Funktion schreiben, die sowohl den Datentyp als auch die Größe
automatisch aus dem Funktionsargument herausdestilliert. Also so, dass
folgender Ausdruck funktioniert:
template<typename T, size_t S>
void my_array_factory(T (*r)[S]);
my_array_factory(new int[3]); // geht natürlich nicht!
my_array_factory(new int[3][1]); // Workaround von James Kanze
Die Idee dahinter ist letztlich immer dieselbe, den Luxus von C++ mit
der Geschwindigkeit von C zu vereinen. Oft geht das mittlerweile ganz
gut. Und die Zahl der (unbemerkten) Programmierfehler hat nach meiner
Erfahrung dabei /deutlich/ abgenommen.
Marcel
--
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 |
|
 |
Tobias Güntner Guest
|
Posted: Sun Feb 19, 2006 2:13 pm Post subject: Re: Returntyp von Operator new und Arrays |
|
|
Marcel Müller wrote:
| Quote: | typedef int my_type[5];
....
Schön und gut, aber wie Alloziere ich denn nun /ein/ Objekt
von Typ int[5]?
new my_type[1]
Es geht nicht anders (auf historischen Grunden).
OK, nicht schön, aber selten.
Die unangenehme Nebenwirkung ist, dass dabei immer der operator new[]
aufgerufen wird und konsequenterweise das Objekt auch mit delete[]
freigegeben werden muss.
|
Bei "new my_type;" doch ebenso, man muss also in jedem Fall delete[]
verwenden. Oder habe ich da jetzt etwas falsch verstanden?
Gruß
Tobias
--
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 |
|
 |
kanze Guest
|
Posted: Mon Feb 20, 2006 2:06 pm Post subject: Re: Returntyp von Operator new und Arrays |
|
|
Tobias Güntner wrote:
| Quote: | Marcel Müller wrote:
typedef int my_type[5];
...
Schön und gut, aber wie Alloziere ich denn nun /ein/ Objekt
von Typ int[5]?
new my_type[1]
Es geht nicht anders (auf historischen Grunden).
OK, nicht schön, aber selten.
Die unangenehme Nebenwirkung ist, dass dabei immer der
operator new[] aufgerufen wird und konsequenterweise das
Objekt auch mit delete[] freigegeben werden muss.
Bei "new my_type;" doch ebenso, man muss also in jedem Fall
delete[] verwenden. Oder habe ich da jetzt etwas falsch
verstanden?
|
Soweit ich weiß, hast du richtig verstanden. Es gibt zwei Art
von new, scalar new und array new. Und die Art wird vom Typ
gewählt, und nicht von der Schreibweise. Bei "new my_type" ist
der allokeirte Typ "Felder[5] von int". Felder, also, und damit
wird array new verwendet. Mit zwei Konsequenzen: der Typ des
Ergebnisses wird vom "T[]" in "T*" umgemappt, statt von "T" in
"T*", und man muss delete[] verwenden.
Ähnlicherwiese, mit "new int (&((*p)()))[ 10 ]" wird scalar new,
und nicht array new, aufgerufen. Der Typ des Ergebnisses ist
also "int (&((**)()))[ 10 ]", und nicht etwa "int (&((*)()))".
Und man muss danach delete, und nicht delete[], verwenden.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
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 |
|
 |
Heinz Saathoff Guest
|
Posted: Tue Feb 21, 2006 10:06 am Post subject: Re: Returntyp von Operator new und Arrays |
|
|
Moin,
| Quote: | Ähnlicherwiese, mit "new int (&((*p)()))[ 10 ]" wird scalar new,
|
Ich muss gestehen, dass ich diese new-expression nicht verstehe. Ist p
hier ein Typ oder eine Variable? Letzteres durfte in einer new-
expression doch gar nicht vorkommen? Dann der Operator '&', der entweder
als Adressoperator oder als Referenz interpretiert wird? Referenzen
lassen sich dorch gar nicht per new allokieren?
| Quote: | und nicht array new, aufgerufen. Der Typ des Ergebnisses ist
also "int (&((**)()))[ 10 ]", und nicht etwa "int (&((*)()))".
^^^^^^^^^^^^^^^^^^^^^^ |
Ist das jetzt ein Zeiger auf einen Funktionzeiger, wo die Funktion eine
Referenz auf ein array mit 10 ints zurückgibt?
- Heinz
--
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 |
|
 |
kanze Guest
|
Posted: Tue Feb 21, 2006 11:06 am Post subject: Re: Returntyp von Operator new und Arrays |
|
|
Heinz Saathoff wrote:
| Quote: | Ähnlicherwiese, mit "new int (&((*p)()))[ 10 ]" wird scalar new,
Ich muss gestehen, dass ich diese new-expression nicht verstehe.
|
Wobei du recht hast.
| Quote: | Ist p hier ein Typ oder eine Variable?
|
Es ist eigentlich ein "Hilfer", das ich vergessen habe, zu
löschen. Bei komplizierten Typausdrücken wie diesem finde ich es
hilfreich, den Ausdruck zuerst zu formulieren, als ob ich eine
Variable definiere, und erst am Ende den Namen der Variable zu
löschen. In der Tat soll das p nicht da sein.
| Quote: | Letzteres durfte in einer new- expression doch gar nicht
vorkommen? Dann der Operator '&', der entweder als
Adressoperator oder als Referenz interpretiert wird?
Referenzen lassen sich dorch gar nicht per new allokieren?
und nicht array new, aufgerufen. Der Typ des Ergebnisses ist
also "int (&((**)()))[ 10 ]", und nicht etwa "int (&((*)()))".
^^^^^^^^^^^^^^^^^^^^^^
Ist das jetzt ein Zeiger auf einen Funktionzeiger, wo die Funktion eine
Referenz auf ein array mit 10 ints zurückgibt?
|
Genau. Und der Ausdruck im new sollte auch so ähnlich aussehen,
ohne den p (mit aber einen * weniger).
Das Ziel war nur, ein Typ zu haben, dessen Name mit einem []
endet, obwohl er keine Feld ist. In der Tat denke ich, dass
solche Type selten vorkomment, und noch seltener dynamisch
allokiert werden. Ich wollte nur darauf hinweisen, dass man auf
die Schreibweise des Parameters von new nicht vertrauen kann;
man muss in allen Fällen zurück auf den richtigen Typ gehen.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
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
|
|