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

10 réponses

1 2
Avatar
Jean-Marc Bourguet
"Michaël Delva" writes:

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;


boost::scoped_ptr n'est pas copiable et pour avoir un operator= defini
par le compilateur, il faut que tous les membres soient copiables.

Je crois qu'il y a un boost::shared_ptr qui l'est.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
rtroadec
"Michaël Delva" wrote in message news:...
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?


Comme pour une classe. En ce qui concerne le pointeur intelligent de
Boost, ce n'est pas copiable (pas de constructeur par copie ni
d'opérateur d'affectation possible), il faut une nouvelle "valeur" de
pointeur pour scoped_ptr.

VC_Timeline& VC_Timeline::operator=(const VC_Timeline& rhs)
{
// empêche auto-affectation
if (this != &rhs)
{
liste_sequences.clear();
liste_sequences = rhs.liste_sequences;
// detruit ptr value du scoped_ptr
delete rhs.Edit_Video.get();
// + reset de éventuellement ici
rhs.Edit_Video.reset(new DS_Edit_Video);
}
return *this;
}

Regis

Avatar
rtroadec
"Michaël Delva" wrote in message news:...
Bonsoir à tous,


Re, erratum,

[coupé]

Comment vous feriez-ça?


En fait, pas comme dans mon post précédent, c'est faux et de sucroit
débile (surtout le delete rhs.Edit_Video.get();), le repas de midi m'a
remis les idées en place.

Simplement :

VC_Timeline& VC_Timeline::operator=(const VC_Timeline& rhs)
{
// empêche auto-affectation
if (this != &rhs)
{
liste_sequences.clear();
liste_sequences = rhs.liste_sequences;
Edit_Video.reset(new DS_Edit_Video);
}
return *this;
}


Regis

Avatar
Fabien LE LEZ
On 28 Sep 2004 03:52:43 -0700, (Targeur fou):

VC_Timeline& VC_Timeline::operator=(const VC_Timeline& rhs)
{
// empêche auto-affectation
if (this != &rhs)
{
liste_sequences.clear();


A quoi sert cette ligne ?

liste_sequences = rhs.liste_sequences;
Edit_Video.reset(new DS_Edit_Video);


Que se passe-t-il si "new DS_Edit_Video" lance une exception ?


--
;-)

Avatar
rtroadec
Fabien LE LEZ wrote in message news:...
On 28 Sep 2004 03:52:43 -0700, (Targeur fou):


Salut,


VC_Timeline& VC_Timeline::operator=(const VC_Timeline& rhs)
{
// empêche auto-affectation
if (this != &rhs)
{
liste_sequences.clear();


A quoi sert cette ligne ?


A rien, en théorie et en pratique. Ou plutôt si, à expliciter une
intention : je vire les éléments du vecteur de l'objet courant avant
d'y recopier les éléments de l'objet rvalue. C'est sûr tout ça est
géré dans l'opérateur d'affectation redéfini pour std::vector et le
clear ne fait que virer les éléments sans désallouer de mémoire mais
je trouve personnellement cela plus lisible.

liste_sequences = rhs.liste_sequences;
Edit_Video.reset(new DS_Edit_Video);


Que se passe-t-il si "new DS_Edit_Video" lance une exception ?


Exception non catchée + core dump.
Vis-à-vis de DS_Edit_Video, j'en sais rien. Vis-à-vis du new, utiliser
set_new_handler par exemple, ou mettre le tout dans un bloc try et
catcher bad_alloc.

Regis


Avatar
Luc Hermitte
(Targeur fou) wrote in
news::

VC_Timeline& VC_Timeline::operator=(const VC_Timeline& rhs)
{
// empêche auto-affectation
if (this != &rhs)
{
liste_sequences.clear();


A quoi sert cette ligne ?


A rien, en théorie et en pratique. Ou plutôt si, à expliciter une
intention : je vire les éléments du vecteur de l'objet courant avant
d'y recopier les éléments de l'objet rvalue. C'est sûr tout ça est
géré dans l'opérateur d'affectation redéfini pour std::vector et le
clear ne fait que virer les éléments sans désallouer de mémoire mais
je trouve personnellement cela plus lisible.



Pire que ça, elle te sert à perdre la robustesse que t'apportait le
vecteur.
Une bonne façon de copier consiste à d'abord faire les réservations, puis
la copie elle-même et enfin à libérer l'ancien. (en lisant entre les
lignes, tu noteras que l'on passe par des temporaires)
Fait correctement, le test contre les auto affectations ne sert alors
plus à rien. En fait, il s'agit d'un faux ami des "temps anciens".
Si il y a plusieurs ressources à gérer on se rajoute une couche
d'abstraction qui sait déjà faire tout ça.



liste_sequences = rhs.liste_sequences;
Edit_Video.reset(new DS_Edit_Video);
Que se passe-t-il si "new DS_Edit_Video" lance une exception ?



Exception non catchée + core dump.


Mais non. On la rattrappe dans le code qui tourne en boucle et qui a
demandé la copie.

Vis-à-vis de DS_Edit_Video, j'en sais rien. Vis-à-vis du new, utiliser
set_new_handler par exemple, ou mettre le tout dans un bloc try et
catcher bad_alloc.


Compliqué et inutile vu que l'on peut faire un truc plus robuste qui soit
simple à maintenir.


--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>



Avatar
Michaël Delva
Pire que ça, elle te sert à perdre la robustesse que t'apportait le
vecteur.
Une bonne façon de copier consiste à d'abord faire les réservations, puis
la copie elle-même et enfin à libérer l'ancien. (en lisant entre les
lignes, tu noteras que l'on passe par des temporaires)
Fait correctement, le test contre les auto affectations ne sert alors
plus à rien. En fait, il s'agit d'un faux ami des "temps anciens".
Si il y a plusieurs ressources à gérer on se rajoute une couche
d'abstraction qui sait déjà faire tout ça.



Ca me donnerait donc quelque chose comme ça?

VC_Timeline& VC_Timeline::operator=(const VC_Timeline& rhs)
{
// empêche auto-affectation
if (this != &rhs)
{
liste_sequences.resize(rhs.liste_sequences.size());
std::copy(rhs.liste_sequences.begin(),rhs.liste_sequences.end
(),liste_sequences);
rhs.liste_sequences.clear();
Edit_Video.reset(new DS_Edit_Video);
}
return *this;
}

Vis-à-vis de DS_Edit_Video, j'en sais rien. Vis-à-vis du new, utiliser
set_new_handler par exemple, ou mettre le tout dans un bloc try et
catcher bad_alloc.


Compliqué et inutile vu que l'on peut faire un truc plus robuste qui soit
simple à maintenir.



C'est quoi "un truc plus robuste qui soit simple à maintenir"??

Merci pour vos réponses!


Avatar
Michaël Delva
"Michaël Delva" wrote in
news::

VC_Timeline& VC_Timeline::operator=(const VC_Timeline& rhs)
{
// empˆche auto-affectation
if (this != &rhs)
{
liste_sequences.resize(rhs.liste_sequences.size());
std::copy(rhs.liste_sequences.begin(),rhs.liste_sequences.end
(),liste_sequences);
rhs.liste_sequences.clear();
Edit_Video.reset(new DS_Edit_Video);
}
return *this;
}


En supposant que ce qui est au dessus est correct, le compilo me demande
maintenant de définir un operator* pour la classe VC_Sequence, pour que
l'algo std::copy puisse fonctionner...

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

VC_Timeline(const VC_Timeline & rhs)

__fastcall VC_Timeline() {}

VC_Timeline& __fastcall operator=(const VC_Timeline & rhs)
};


struct VC_Sequence
{
bool is_image;
LONGLONG frame_preview;
WideString path_video;

__fastcall VC_Sequence(const WideString & path_video, bool is_image,
const LONGLONG & frame)
: is_image(is_image),frame_preview(frame),path_video(path_video)
{}

__fastcall VC_Sequence() {}
};

Seulement j'ai jamais défini un tel operateur... Comment je dois m'y
prendre??

Merci d'avance

Avatar
Luc Hermitte
"Michaël Delva" wrote in
news::

Pire que ça, elle te sert à perdre la robustesse que t'apportait le
vecteur. Une bonne façon de copier consiste à d'abord faire les
réservations, puis la copie elle-même et enfin à libérer l'ancien.
(en lisant entre les lignes, tu noteras que l'on passe par des
temporaires) Fait correctement, le test contre les auto affectations
ne sert alors plus à rien. En fait, il s'agit d'un faux ami des
"temps anciens". Si il y a plusieurs ressources à gérer on se rajoute
une couche d'abstraction qui sait déjà faire tout ça.



Ca me donnerait donc quelque chose comme ça?

VC_Timeline& VC_Timeline::operator=(const VC_Timeline& rhs)
{
// empêche auto-affectation
if (this != &rhs)


inutile si bien fait.

{
liste_sequences.resize(rhs.liste_sequences.size());
std::copy(rhs.liste_sequences.begin(),rhs.liste_sequences.end
(),liste_sequences);


Pourquoi ne pas utiliser l'opérateur = ? Sa syntaxe est trop simple ?
(en plus, il manque un begin()).

rhs.liste_sequences.clear();


rhs est const....

Edit_Video.reset(new DS_Edit_Video);
}
return *this;
}


Je voulais parler de (ici il n'y a que deux ressources, on peut s'en
sortir ainsi) :
{
std::auto_ptr<DS_Edit_Video> tmp(new DS_Edit_Video);
liste_sequences = rhs.liste_sequences;
Edit_Video = tmp.release();
}

Toutes tes accrobaties autour de la recopie de la liste sont inefficaces
et font perdre toutes les bonnes propriétés de l'opération de recopie des
conteneurs standard.

Vis-à-vis de DS_Edit_Video, j'en sais rien. Vis-à-vis du new,
utiliser set_new_handler par exemple, ou mettre le tout dans un bloc
try et catcher bad_alloc.


Compliqué et inutile vu que l'on peut faire un truc plus robuste qui
soit simple à maintenir.



C'est quoi "un truc plus robuste qui soit simple à maintenir"??


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

void VC_Timeline::swap(VC_Timeline& other)
{
liste_sequences.swap(other.liste_sequences);
swap_qui_va_bien(Edit_Video, other.Edit_Video);
}

Regarde ce qu'il se passe si il y a des exceptions dans _toutes_ les
instructions qui peuvent en lancer dans tes codes et dans ceux que j'ai
donné. Voit ce qu'il advient des ressources allouées et de l'état de
l'objet que l'on "remplace".

--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>



Avatar
Michaël Delva
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?

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?
* le constructeur par copie est correct, ou bien je dois là aussi utiliser
la fonction swap? Si il est correct comme ça, comment attribuer
correctement Edit_Video? Parce que là je crée une nouvelle instance...

Merci d'avance...
1 2