C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

uninitialized_copy

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Markus Moll
Guest





PostPosted: Fri Mar 03, 2006 4:06 pm    Post subject: uninitialized_copy Reply with quote



Hallo

Mal angenommen, ich habe eine Klasse (T), deren Objekte _wirklich_ teuer zu
konstruieren sind, oder eine, die keinen Default-Konstruktor besitzt.

Jetzt möchte ich eine Kopie eines Arrays von T anlegen.
Ich dachte daran, rohen Speicher mit T* arr = std::operator new[](n *
sizeof(T)) anzufordern, und dann per std::uninitialized_copy(orig, orig+n,
arr) das Originalarray orig hineinzukonstruieren.

Allerdings frage ich mich nun: Ist der einzig korrekte Weg, das ganze
rückgängig zu machen, über arr zu iterieren, auf jedem Objekt einen
Pseudodestruktoraufruf zu machen und den Speicher mit std::operator
delete[](arr) wieder freizugeben?

Ich dachte ursprünglich, ich könne einfach delete[] arr; benutzen, aber das
ist wohl undefiniert (da arr nicht mit new[] erzeugt wurde).

Gruß
Markus

--
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
Falk Tannhäuser
Guest





PostPosted: Fri Mar 03, 2006 6:06 pm    Post subject: Re: uninitialized_copy Reply with quote



Markus Moll wrote:
Quote:
Jetzt möchte ich eine Kopie eines Arrays von T anlegen.
Ich dachte daran, rohen Speicher mit T* arr = std::operator new[](n *
sizeof(T)) anzufordern, und dann per std::uninitialized_copy(orig, orig+n,
arr) das Originalarray orig hineinzukonstruieren.

Warum eigentlich nicht
std::vector<T> arr(orig, orig+n);
?

Quote:
Allerdings frage ich mich nun: Ist der einzig korrekte Weg, das ganze
rückgängig zu machen, über arr zu iterieren, auf jedem Objekt einen
Pseudodestruktoraufruf zu machen und den Speicher mit std::operator
delete[](arr) wieder freizugeben?

Ich dachte ursprünglich, ich könne einfach delete[] arr; benutzen, aber das
ist wohl undefiniert (da arr nicht mit new[] erzeugt wurde).

.... und demzufolge die Anzahl `n' der aufzurufenden Destruktoren
nicht dort auffindbar ist, wo es für das delete[] erwartet wird.

MfG
Falk

--
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
Christoph Bartoschek
Guest





PostPosted: Fri Mar 03, 2006 9:06 pm    Post subject: Re: uninitialized_copy Reply with quote



Markus Moll wrote:

Quote:
Mal angenommen, ich habe eine Klasse (T), deren Objekte wirklich teuer
zu konstruieren sind, oder eine, die keinen Default-Konstruktor besitzt.

Jetzt möchte ich eine Kopie eines Arrays von T anlegen.
Ich dachte daran, rohen Speicher mit T* arr = std::operator new[](n *
sizeof(T)) anzufordern, und dann per std::uninitialized_copy(orig, orig+n,
arr) das Originalarray orig hineinzukonstruieren.

Ein std::uninitialized_copy benutzt den Kopierkonstruktor, um die neuen
Elemente zu erzeugen. Du sparst also mit dieser Methode keinen
Konstruktoraufruf.

Um rohen Speicher anzufordern, würde ich malloc benutzen:

T * arr = static_cast<T *>(malloc(n * sizeof(*arr)));

Quote:
Allerdings frage ich mich nun: Ist der einzig korrekte Weg, das ganze
rückgängig zu machen, über arr zu iterieren, auf jedem Objekt einen
Pseudodestruktoraufruf zu machen und den Speicher mit std::operator
delete[](arr) wieder freizugeben?

Ja, das ist der einzige weg, wobei ich hier dann free nehmen würde:

free(arr);

Christoph

--
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
Mario Schunda
Guest





PostPosted: Fri Mar 03, 2006 11:06 pm    Post subject: Re: uninitialized_copy Reply with quote

Hallo Markus

Meiner Meinung geht es so:

class cHuhu
{
public:
cHuhu(int J) { std::cout << "Konstructor " << J << std::endl; };
~cHuhu() { std::cout << "Destructor" << std::endl; };
};

template< class T >
T* CreateUninitialized(const T& Des)
{
T* pSrc = reinterpret_cast<T*>(new unsigned char [sizeof(T)]);
std::copy(&Des,
&Des + 1,
std::raw_storage_iterator<T*, T>(pSrc));
return pSrc;
};

int main(int argc, char **argv)
{
cHuhu Hu1(2);
cHuhu* pHu = CreateUninitialized(Hu1);

delete pHu;

........


Die letzte Zeile zeigt das Du delete Normal auf den Type anwendest da Du ja
eine fertig und Korrekt angelegt Klasse hast. So kannst Du auch den
Destruktor der Klasse benutzen.

Mario

--
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
Rolf Magnus
Guest





PostPosted: Sat Mar 04, 2006 10:06 am    Post subject: Re: uninitialized_copy Reply with quote

Christoph Bartoschek wrote:

Quote:
Markus Moll wrote:

Mal angenommen, ich habe eine Klasse (T), deren Objekte wirklich teuer
zu konstruieren sind, oder eine, die keinen Default-Konstruktor besitzt.

Jetzt möchte ich eine Kopie eines Arrays von T anlegen.
Ich dachte daran, rohen Speicher mit T* arr = std::operator new[](n *
sizeof(T)) anzufordern, und dann per std::uninitialized_copy(orig,
orig+n, arr) das Originalarray orig hineinzukonstruieren.

Ein std::uninitialized_copy benutzt den Kopierkonstruktor, um die neuen
Elemente zu erzeugen. Du sparst also mit dieser Methode keinen
Konstruktoraufruf.

Aber erst default-konstruieren und dann zuweisen ist aufwendiger.

Quote:
Um rohen Speicher anzufordern, würde ich malloc benutzen:

T * arr = static_cast<T *>(malloc(n * sizeof(*arr)));

Warum? Ich würde operator new so verwenden, wie Markus das oben getan hat,
schon alleine, um mir den Cast zu ersparen.

--
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 Moll
Guest





PostPosted: Sat Mar 04, 2006 2:06 pm    Post subject: Re: uninitialized_copy Reply with quote

Hallo

Rolf Magnus wrote:

Quote:
Christoph Bartoschek wrote:
Um rohen Speicher anzufordern, würde ich malloc benutzen:

T * arr = static_cast<T *>(malloc(n * sizeof(*arr)));

Warum? Ich würde operator new so verwenden, wie Markus das oben getan hat,
schon alleine, um mir den Cast zu ersparen.

Das war allerdings mein Fehler. Operator new benötigt auch einen cast, den
habe ich einfach vergessen.

Ich bin leider gezwungen, ein dynamisches C-style array zu verwenden (geht
um Performance bei ausgeschalteten Optimierungen Razz). Insofern muß ich mir
quasi das "nötigste" des vector selbst schreiben, dazu gehört eben die
Konstruktion als Kopie eines anderen Arrays. Hab das jetzt auch soweit
korrigiert, daß nur noch operator new[], placement new, Destruktor und
operator delete[] (in dieser Reihenfolge) beteiligt sind.

Gibt es zwischen T und Array von T eigentlich möglicherweise
Alignment-Unterschiede? (Frage wegen operator new[] vs operator new)

Danke
Gruß
Markus

--
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
Christoph Bartoschek
Guest





PostPosted: Sat Mar 04, 2006 3:06 pm    Post subject: Re: uninitialized_copy Reply with quote

Rolf Magnus wrote:

Quote:
Um rohen Speicher anzufordern, würde ich malloc benutzen:

T * arr = static_cast<T *>(malloc(n * sizeof(*arr)));

Warum? Ich würde operator new so verwenden, wie Markus das oben getan hat,
schon alleine, um mir den Cast zu ersparen.


Stimmt wohl, dass malloc nicht besser als operator new[] ist. Aber auch
operator new[] gibt nur void * zurück (und ist übrigends nicht im namespace
std), so dass der cast immer noch notwendig ist. Dadurch ist malloc doch
kürzer.

Zum Testen:

int main() {
int * arr = operator new[](10 * sizeof(*arr));
operator delete[](arr);
}

Ergibt hier:

mem.C: In function »int main()«:
mem.C:2: Fehler: ungültige Umwandlung von »void*« in »int*«


Christoph

--
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
Jakob Bieling
Guest





PostPosted: Sat Mar 18, 2006 9:27 pm    Post subject: Re: uninitialized_copy Reply with quote

Markus Moll <moll (AT) rbg (DOT) informatik.tu-darmstadt.de> wrote:

Quote:
Mal angenommen, ich habe eine Klasse (T), deren Objekte _wirklich_
teuer zu konstruieren sind, oder eine, die keinen Default-Konstruktor
besitzt.

Jetzt möchte ich eine Kopie eines Arrays von T anlegen.
Ich dachte daran, rohen Speicher mit T* arr = std::operator new[](n *
sizeof(T)) anzufordern, und dann per std::uninitialized_copy(orig,
orig+n, arr) das Originalarray orig hineinzukonstruieren.

Allerdings frage ich mich nun: Ist der einzig korrekte Weg, das ganze
rückgängig zu machen, über arr zu iterieren, auf jedem Objekt einen
Pseudodestruktoraufruf zu machen und den Speicher mit std::operator
delete[](arr) wieder freizugeben?

Mit

template <typename T>
void destruct (T& t) { t.~T (); }

kannst du std::for_each benutzen. Ist dann im Endeffekt zwar das
gleiche wie ueber alle einzeln zu iterieren, nur eben schoen lesbar
verpackt:

std::for_each (arr, arr + n, destruct <T>);

hth
--
jb

(reply address in rot13, unscramble first)


--
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
Jakob Bieling
Guest





PostPosted: Sat Mar 18, 2006 9:41 pm    Post subject: Re: uninitialized_copy Reply with quote

Mario Schunda <weg_mario@familie-schunda.de> wrote:
Quote:
Hallo Markus

Meiner Meinung geht es so:

class cHuhu
{
public:
cHuhu(int J) { std::cout << "Konstructor " << J << std::endl; };
~cHuhu() { std::cout << "Destructor" << std::endl; };
};

template< class T
T* CreateUninitialized(const T& Des)
{
T* pSrc = reinterpret_cast<T*>(new unsigned char [sizeof(T)]);

Halte ich fuer keine so gute Idee. Nach diesem reinterpret_cast ist
das ganze nicht mehr portable.

Quote:
std::copy(&Des,
&Des + 1,
std::raw_storage_iterator<T*, T>(pSrc));
return pSrc;
};

int main(int argc, char **argv)
{
cHuhu Hu1(2);
cHuhu* pHu = CreateUninitialized(Hu1);

delete pHu;


Hier hast du dann wirklich undefined behaviour, da du jetzt delete
aber ein paar Zeilen weiter oben new[] benutzt. Mal abgesehn davon dass
char und cHuhu gaenzlich unverwandt sind und es deshalb selbst mit
delete[] nich besser waere.

Den Ansatz mit ::operator new und ::operator delete find ich da
wesentlich besser.
--
jb

(reply address in rot13, unscramble first)


--
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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.