OVH Cloud OVH Cloud

std::vector copy constructor

34 réponses
Avatar
Cyrille \cns\ Szymanski
Est-il possible d'utiliser std::vector de telle sorte que les appels à
resize construisent chaque objet plutôt que d'utiliser un copy
constructor ?

L'idée est d'avoir un fonctionnement similaire à celui du code suivant
mais en évitant la copie de l'objet et le gâchis de mémoire :

vector<MyClass> vec;
vec.reserve(20);
for( int i=0; i<10; ++i )
{
vec.push_back( *(new MyClass()) );
}

A défaut, quelle est la façon propre de faire un
// construire l'objet
MyClass *tmp = new MyClass();
// le placer dans le tableau
vec.push_back( *tmp );
// limérer la mémoire sans appeler le destructeur
free( tmp );

Je veux bien fournir mon propre copy constructor et lui faire créer un
nouvel objet de toutes pièces, mais cela est d'une part détourner son
vrai objectif et d'autre part cela risque d'interférer avec les vraies
copies d'objet.

--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/

4 réponses

1 2 3 4
Avatar
Arnaud Debaene
Jean-Marc Bourguet wrote:
"Cyrille "cns" Szymanski" writes:

Il doit sûrement y avoir des raisons à cela, mais je trouve ça
horrible et au risque de me faire incendier, un realloc() bien
utilisé est quand même vachement pratique.


Un realloc ce n'est possible que pour des POD.


Pire que cà : que pour les PODs sans pointeurs (ou objets "pointeuresques"
du type handle), à moins de vouloir explicitement faire une "shallow copy",
ce qui est rarement le cas.

Arnaud


Avatar
Gabriel Dos Reis
"Cyrille "cns" Szymanski" writes:

| >> A défaut, quelle est la façon propre de faire un
| >> // construire l'objet
| >> MyClass *tmp = new MyClass();
| >> // le placer dans le tableau
| >> vec.push_back( *tmp );
| >> // limérer la mémoire sans appeler le destructeur
| >> free( tmp );
| >
| > Sans répondre à la question:
| >
| > new -> delete (et pas free)
| >
|
| Oui, j'ai délibérément utilisé free ici pour que le destructeur n e soit pas
| appelé.

C'est du fonctionnement indéfini. Rien ne dit que la mémoire obtenue
par operator new() peut être libérée par free().

C'est curieux cette façon que les gens ont d'insister que leurs
programmes fassent n'importe quoi en prétendant qu'ils font de
l'optimisation.

-- Gaby
Avatar
Christophe Lephay
"Arnaud Debaene" a écrit dans le message de
news:3f480118$0$1141$
à moins de vouloir explicitement faire une "shallow copy",


C'est quoi une "shallow copy" ?

Chris

Avatar
drkm
--=-=- Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: quoted-printable

Loïc Joly writes:

Cyrille "cns" Szymanski wrote:

struct MyClass {
HANDLE hwnd;
MyClass() {
hwnd = OpenHandle();
}
~MyClass() {
CloseHandle( hwnd );
}
};
Faire vector<MyClass> vec;
for( i=0; i<10; ++i) { vec.push_back( MyClass() );
}
ne fonctionne pas car le handle est fermé tout de suite.


En fait, comme on l'a dit, pour pouvoir mettre une classe dans un
vector, elle DOIT pouvoir être copiée (avec la sémentique du mot
copier). Ce n'est pas le cas de cette classe. Dans cet example
windowsien, un truc qui ressemble à ça devrait marcher :

MyClass::MyClass(MyClass const &mc)
{
DuplicateHandle(GetCurrentProcess(), mc.hwnd, GetCurrentProcess(), hwn d);
}


--=-=- Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable


En fait, pour être quelque peu plus général, je pense que la clef
est que son exemple que tu cites ici, ainsi que celui que tu as snipé,
ces deux exemples opèrent l'acquisition d'un ressource dans le
constructeur et la libèrent dans le destructeur.

Il faut alors définir le comportement en cas de copie : changement
de propriétaire, copie, etc. Je pense que ce comportement, au moyen
du constructeur de copie, doit dans ces cas toujours être défini. Un
des comportements possibles étant par ailleurs d'interdire la copie,
ce qui est la cas ici.

Une fois cela défini, on sait si std::vector<> est utilisable ou non
avec cette classe. On a décidé soit que les instances d'une clas se
sont copiables, soit qu'elles ne le sont pas.

Si elles ne le sont pas, mais que l'on souhaite néanmoins utiliser
std::vector<>, il faut voir si l'on peut modifier la classe pour la
rendre copiable.

--drkm

--=-=-=--


1 2 3 4