Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

objet et vector

9 réponses
Avatar
pasdespam
bonsoir,

pseudo-code :

class A {

short a;
short b;
short c;

A& operator=(const A& src) { a=src.a; b=src.b; c=src.c; };

};

class B {

A* ptrA;

B(): ptrA(new A) {};

B(const B& src) : ptrA(new A) { *ptrA = *(src.ptrA); }; //copie profonde

B& operator=(const B& src) { *ptrA = *(src.ptrA); }; //copie profonde;

~B() { delete ptrA;};

};

les objets de type B sont ils "stockables" dans un vector?

9 réponses

Avatar
Fabien LE LEZ
On Tue, 19 May 2009 16:50:56 +0200, (Bruno Causse):

A& operator=(const A& src) { a=src.a; b=src.b; c=src.c; };



Totalement inutile -- l'opérateur de copie automatiquement généré
ferait la même chose.

class B {

A* ptrA;



Préfère boost::shared_ptr<> autant que possible.

les objets de type B sont ils "stockables" dans un vector?



Oui (sous réserve que les constructeur et opérateur de copie sont bien
publics).
Un pointeur est copiable, une référence ne l'est pas.

struct Copiable { A* ptr; }
struct NonCopiable { A& ptr; }
Avatar
James Kanze
On May 19, 5:13 pm, Fabien LE LEZ wrote:
On Tue, 19 May 2009 16:50:56 +0200, (Bruno Causse):



>A& operator=(const A& src) { a=src.a; b=src.b; c=src.c; };



Totalement inutile -- l'opérateur de copie automatiquement
généré ferait la même chose.



De même pour son constructeur de copie d'A.

>class B {



>A* ptrA;



Préfère boost::shared_ptr<> autant que possible.



Pourquoi. Ici, d'après ce qu'il semble vouloir faire, il ne
convient pas du tout. (Ici, d'après son exemple, l'allocation
dynamique ne convient pas du tout. Mais je suppose que c'est
juste pour avoir un exemple.)

>les objets de type B sont ils "stockables" dans un vector?



Oui (sous réserve que les constructeur et opérateur de copie
sont bien publics). Un pointeur est copiable, une référence
ne l'est pas.



struct Copiable { A* ptr; }
struct NonCopiable { A& ptr; }



Un pointeur est copiable, mais la copie n'a pas forcément la
sémantique voulue. Il a fourni et le constructeur de copie, et
l'opérateur d'affectation, avec la sémantique qu'il voulait.
C'est ce qu'il faut pour que l'objet puisse être mis dans une
collection standard.

--
James Kanze (GABI Software) email:
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
Avatar
pasdespam
James Kanze wrote:

On May 19, 5:13 pm, Fabien LE LEZ wrote:
> On Tue, 19 May 2009 16:50:56 +0200, (Bruno Causse):

> >A& operator=(const A& src) { a=src.a; b=src.b; c=src.c; };

> Totalement inutile -- l'opérateur de copie automatiquement
> généré ferait la même chose.




en fait je copie mes objets A a l'aide de memcpy

memcpy(a, src.a sizeof(A));

cela fonctionne sur powerPC et i386 mais est ce portable?


De même pour son constructeur de copie d'A.

> >class B {

> >A* ptrA;

> Préfère boost::shared_ptr<> autant que possible.

Pourquoi. Ici, d'après ce qu'il semble vouloir faire, il ne
convient pas du tout. (Ici, d'après son exemple, l'allocation
dynamique ne convient pas du tout. Mais je suppose que c'est
juste pour avoir un exemple.)



oui c'etait un exemple,
Avatar
pjb
(Bruno Causse) writes:

James Kanze wrote:

On May 19, 5:13 pm, Fabien LE LEZ wrote:
> On Tue, 19 May 2009 16:50:56 +0200, (Bruno Causse):

> >A& operator=(const A& src) { a=src.a; b=src.b; c=src.c; };

> Totalement inutile -- l'opérateur de copie automatiquement
> généré ferait la même chose.




en fait je copie mes objets A a l'aide de memcpy

memcpy(a, src.a sizeof(A));

cela fonctionne sur powerPC et i386 mais est ce portable?



PCQJS, ça devrait être parfaitement portable.

Mais on pourrait imaginer une implémentation trés particulière et trés
marginale, où il serait plus intéressant de copier champ par champ.
Mais à moins de ne pas être conforme, elle devrait quand même
fonctionner correctement avec memcpy.

--
__Pascal Bourguignon__
Avatar
Gabriel Dos Reis
(Bruno Causse) writes:

| James Kanze wrote:

On May 19, 5:13 pm, Fabien LE LEZ wrote:
> On Tue, 19 May 2009 16:50:56 +0200, (Bruno Causse):

> >A& operator=(const A& src) { a=src.a; b=src.b; c=src.c; };

> Totalement inutile -- l'opérateur de copie automatiquement
> généré ferait la même chose.






| en fait je copie mes objets A a l'aide de memcpy
|
| memcpy(a, src.a sizeof(A));
|
| cela fonctionne sur powerPC et i386 mais est ce portable?

Ce n'est pas garanti par la sematique officielle de C++.
Si tu as une classe comme A, les seules manières portables (et efficaces !)
de les copier sont :
(1) l'opérateur d'affectation et de copie (operator=); ou
(2) le constructeur de copie.

C'est assez simple ainsi.

-- Gaby
Avatar
James Kanze
On May 20, 11:06 am, (Bruno Causse) wrote:
James Kanze wrote:
> On May 19, 5:13 pm, Fabien LE LEZ wrote:
> > On Tue, 19 May 2009 16:50:56 +0200, (Bruno Causse):



> > >A& operator=(const A& src) { a=src.a; b=src.b; c=src.c; };



> > Totalement inutile -- l'opérateur de copie automatiquement géné ré ferait
> > la même chose.



en fait je copie mes objets A a l'aide de memcpy



memcpy(a, src.a sizeof(A));



cela fonctionne sur powerPC et i386 mais est ce portable?



En général, non. C'est un comportement indéfini si l'objet a un
constructeur non-trivial.

--
James Kanze (GABI Software) email:
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
Avatar
James Kanze
On May 20, 11:21 am, (Pascal J. Bourguignon)
wrote:
(Bruno Causse) writes:
> James Kanze wrote:



>> On May 19, 5:13 pm, Fabien LE LEZ wrote:
>> > On Tue, 19 May 2009 16:50:56 +0200, (Bruno Causse) :



>> > >A& operator=(const A& src) { a=src.a; b=src.b; c=src.c; };



>> > Totalement inutile -- l'opérateur de copie automatiquement
>> > généré ferait la même chose.



> en fait je copie mes objets A a l'aide de memcpy



> memcpy(a, src.a sizeof(A));



> cela fonctionne sur powerPC et i386 mais est ce portable?



PCQJS, ça devrait être parfaitement portable.



Mais on pourrait imaginer une implémentation trés particulière
et trés marginale, où il serait plus intéressant de copier
champ par champ. Mais à moins de ne pas être conforme, elle
devrait quand même fonctionner correctement avec memcpy.



Ça dépend des objets. S'ils contient d'autres objets, du genre
std::string, je ne connais pas de compilateur où ça marche. Et
s'il y a de l'héritage virtuel, il peut y avoir des surprises.
Si l'objet contient une réfèrence, il y aurait aussi un
comportement nettement différent que l'affectation membre par
membre.

C'est un comportement indéfini, en tout cas, dès que l'objet
n'est plus un POD. Et ça risque de ne pas avoir la sémantique
voulue dès qu'il y a des pointeurs.

Dans l'ensemble, memcpy (comme tant d'autres choses héritées de
C) est à proscrire.

--
James Kanze (GABI Software) email:
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
Avatar
James Kanze
On May 20, 6:41 pm, Gabriel Dos Reis wrote:
(Bruno Causse) writes:



| James Kanze wrote:



>> On May 19, 5:13 pm, Fabien LE LEZ wrote:
>> > On Tue, 19 May 2009 16:50:56 +0200, (Bruno Causse) :



>> > >A& operator=(const A& src) { a=src.a; b=src.b; c=src.c; };



>> > Totalement inutile -- l'opérateur de copie automatiquement
>> > généré ferait la même chose.



| en fait je copie mes objets A a l'aide de memcpy



| memcpy(a, src.a sizeof(A));



| cela fonctionne sur powerPC et i386 mais est ce portable?



Ce n'est pas garanti par la sematique officielle de C++.



Sauf si la classe est une PODS (ce qui n'était pas son cas).
Aussi, même si ça a l'air de fonctionner, il peut cesser de
fonctionner avec le moindre petit changement (l'ajoute d'un
membre de type std::string, etc.).

Si tu as une classe comme A, les seules manières portables (et
efficaces !)
de les copier sont :
(1) l'opérateur d'affectation et de copie (operator=); ou
(2) le constructeur de copie.



C'est assez simple ainsi.



Je crois que le point est là. Si la classe est assez simple pour
que memcpy fonctionne correctement, le constructeur de copie et
l'affectation fournis par défaut par le compilateur
fonctionneront aussi. Et sont probablement plus efficace, et en
termes de temps de développement, et en termes de performance.

--
James Kanze (GABI Software) email:
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
Avatar
Gabriel Dos Reis
James Kanze writes:

| On May 20, 6:41 pm, Gabriel Dos Reis wrote:
(Bruno Causse) writes:



| James Kanze wrote:



>> On May 19, 5:13 pm, Fabien LE LEZ wrote:
>> > On Tue, 19 May 2009 16:50:56 +0200, (Bruno Causse):



>> > >A& operator=(const A& src) { a=src.a; b=src.b; c=src.c; };



>> > Totalement inutile -- l'opérateur de copie automatiquement
>> > généré ferait la même chose.



| en fait je copie mes objets A a l'aide de memcpy



| memcpy(a, src.a sizeof(A));



| cela fonctionne sur powerPC et i386 mais est ce portable?



Ce n'est pas garanti par la sematique officielle de C++.





| Sauf si la classe est une PODS (ce qui n'était pas son cas).

Je repondais spécifiquement à la question posée -- i.e. le cas présenté
qui n'est pas un POD.

| Aussi, même si ça a l'air de fonctionner, il peut cesser de
| fonctionner avec le moindre petit changement (l'ajoute d'un
| membre de type std::string, etc.).

Si tu as une classe comme A, les seules manières portables (et
efficaces !)
de les copier sont :
(1) l'opérateur d'affectation et de copie (operator=); ou
(2) le constructeur de copie.



C'est assez simple ainsi.





| Je crois que le point est là. Si la classe est assez simple pour
| que memcpy fonctionne correctement, le constructeur de copie et
| l'affectation fournis par défaut par le compilateur
| fonctionneront aussi. Et sont probablement plus efficace, et en
| termes de temps de développement, et en termes de performance.