OVH Cloud OVH Cloud

operator=

14 réponses
Avatar
Michaël Delva
Bonsoir à tous,

actuellement j'ai la classe suivante:

//------------------------------------------------------------------------
struct VC_Timeline
{
DS_Edit_Video * Edit_Video;
std::vector<VC_Sequence> liste_sequences;
};

et son utilisation:

std::map<AnsiString,VC_Timeline> liste_timelines;

VC_Timeline timeline;
timeline.Edit_Video = new DS_Edit_Video;

liste_timelines[nom_cle] = timeline;





Je voudrais la changer comme suit:

struct VC_Timeline
{
boost::scoped_ptr<DS_Edit_Video> Edit_Video;
std::vector<VC_Sequence> liste_sequences;
};

std::map<AnsiString,VC_Timeline> liste_timelines;

VC_Timeline timeline;
timeline.Edit_Video.reset(new DS_Edit_Video);

liste_timelines[nom_cle] = timeline;


Pour la dernière ligne le compilo me demande de définir un operator=

Mais je n'arrive pas à le définir correctement.

Comment vous feriez-ça?

Merci d'avance

4 réponses

1 2
Avatar
Fabien LE LEZ
On 29 Sep 2004 00:45:39 GMT, "Michaël Delva"
:

Un temporaire a été utilisé pour le paramètre '__a' dans l'appel à
'_STL::void swap<DS_Edit_Video *>(DS_Edit_Video * &,DS_Edit_Video * &)'


Généralement, ce message indique que tu essaies de passer une
constante en paramètre alors que la fonction prend une référence non
constante -- il y a création d'un temporaire, qui lui est passé par
référence non constante.

std::swap(Edit_Video.get(), other.Edit_Video.get());


Ben voilà, c'est ça : "other" est constant, donc tenter de le modifier
n'apporte rien de bon.


--
;-)

Avatar
kanze
"Michaël Delva" wrote in message
news:...

Merci pour tes réponses, tout ça marche très bien...

J'ai juste un avertissement que je ne comprends pas:

Un temporaire a été utilisé pour le paramètre '__a' dans l'appel à
'_STL::void swap<DS_Edit_Video *>(DS_Edit_Video * &,DS_Edit_Video * &)'

struct VC_Timeline
{
boost::scoped_ptr<DS_Edit_Video> Edit_Video;
std::vector<VC_Sequence> liste_sequences;

__fastcall VC_Timeline()
{
Edit_Video.reset(new DS_Edit_Video);
}

__fastcall VC_Timeline(const VC_Timeline & rhs)
{
Edit_Video.reset(new DS_Edit_Video);
liste_sequences = rhs.liste_sequences;
}

VC_Timeline & __fastcall operator=(const VC_Timeline & rhs)
{
VC_Timeline tmp(rhs);
swap(tmp);
return *this;
}

void __fastcall VC_Timeline::swap(VC_Timeline & other)
{
liste_sequences.swap(other.liste_sequences);
std::swap(Edit_Video.get(), other.Edit_Video.get());
}
};

Pourquoi j'ai cet avertissement?


Parce que ton code est illégal. Il aurait été légal autrefois ; alors,
le compilateur le permet, pour ne pas casser du code, mais avertir.

En fait, ton code est un bon exemple de pourquoi on l'a rendu illégal.
Tu appelles std::swap sur des valeurs de rétour des fonctions get. C-à-d
des temporaires. Tu échanges donc les valeurs temporaires, mais tu ne
touches pas aux instances de Edit_Video.

Pourquoi pas simplement :
swap( Edit_Video, other.Edit_Video ) ;
voire même :
Edit_Video.swap( other.Edit_Video ) ;

(Je préfère le deuxième. Ça rend clair que mon code se base sur une
implémentation particulière de swap.)

Sinon j'ai deux autres questions:
* est-ce parce que tu fais toi même le swap dans l'operator= que tu
te dispenses du test de l'auto-affectation?


Disons plus généralement : c'est parce qu'on crée tous les éléments
nouveaux avant de modifier quoique ce soit dans l'objet cible qu'on peut
se passer du test de l'auto-affectation.

* le constructeur par copie est correct, ou bien je dois là aussi
utiliser la fonction swap?


Avec swap, tu échanges la nouvelle valeur avec l'ancienne. Où est-ce que
tu vas trouver une ancienne valeur dans le constructeur de copie ?

En fait, je l'aurais écris :

VC_Timeline::VC_Timeline(
VC_Timeline const& other )
: Edit_Video( new DS_Edit_Video( other.Edit_Video ) )
, liste_sequences( other.liste_sequences )
{
}

Note que j'ai fait une copie profonde de l'autre Edit_Video. Sans savoir
à quoi sert cette classe, c'est difficile à dire ce qu'il faut
réelement, mais ta version n'a pas pris en compte sa valeur dans l'objet
qu'on copiait.

Si il est correct comme ça, comment attribuer correctement Edit_Video?
Parce que là je crée une nouvelle instance...


Toute la question est : à quoi sert cette classe (et cette instance).
Si, par exemple, elle est immutable, ou au moins, les VC_Timeline ne le
modifie jamais, ou si pour n'importe quelle raison, plusieurs
VC_Timeline peuvent partager la même instance, c'est peut-être que
shared_ptr conviendrait mieux. Et sinon, je me pose la question :
pourquoi le pointeur. Ne serait-il pas plus simple de se passer du
pointeur complétement. Et si tu te sers d'un pointeur parce qu'en fait,
il y a du polymorphisme en jeu, alors, il va falloir une fonction clone
s'il te faut une copie profonde, parce que le constructeur de copie,
lui, n'est pas polymorphique.

--
James Kanze GABI Software http://www.gabi-soft.fr
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
Michaël Delva
Merci beaucoup pour toutes ces réponses...

J'ai fini par me passer du scoped_ptr pour le remplacer par un shared_ptr,
et tout fonctionne très bien maintenant.

struct VC_Timeline
{
private:
void __fastcall VC_Timeline::swap(VC_Timeline & other)
{
liste_sequences.swap(other.liste_sequences);
std::swap(Edit_Video, other.Edit_Video);
}

public:
boost::shared_ptr<DS_Edit_Video> Edit_Video;
std::vector<VC_Sequence> liste_sequences;

__fastcall VC_Timeline() : Edit_Video(new DS_Edit_Video) {}
__fastcall VC_Timeline(const VC_Timeline & rhs) : Edit_Video
(rhs.Edit_Video),liste_sequences(rhs.liste_sequences) {}

VC_Timeline & __fastcall operator=(const VC_Timeline & rhs)
{
VC_Timeline tmp(rhs);
swap(tmp);
return *this;
}
};
Avatar
kanze
Fabien LE LEZ wrote in message
news:...

On 29 Sep 2004 00:45:39 GMT, "Michaël Delva"
:

Un temporaire a été utilisé pour le paramètre '__a' dans l'appel à
'_STL::void swap<DS_Edit_Video *>(DS_Edit_Video * &,DS_Edit_Video * &)'


Généralement, ce message indique que tu essaies de passer une
constante en paramètre alors que la fonction prend une référence non
constante -- il y a création d'un temporaire, qui lui est passé par
référence non constante.


Il y a création d'un temporaire, mais non pour la raison que tu dis. Il
n'y a pas d'objet constant ici. C'est la valeur de rétour d'une fonction
qui est le temporaire.

std::swap(Edit_Video.get(), other.Edit_Video.get());


Ben voilà, c'est ça : "other" est constant, donc tenter de le modifier
n'apporte rien de bon.


Sauf que dans son code, other n'était pas constant. Le problème, c'est
qu'il ne tente pas à modifier other (bien que ce soit ce qu'il veut),
mais plutôt les valeurs de retour des fonctions get().

--
James Kanze GABI Software http://www.gabi-soft.fr
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


1 2