Je voudrais qu'une fonction renvoie un objet encapsulant
un pointeur allou=E9e par la fonction, de fa=E7on =E0 ce que
l'appelant n'ait pas =E0 se soucier de la lib=E9ration du
pointeur : elle sera faite quand l'objet retourn=E9 quitera
la port=E9e dans l'appelant.
exemple
class class amp {
public:
void * m_p;
amp( void * pAllocated ) : m_p( pAllocated ) {}
~amp() { /* lib=E9ration de p */ }
};
Mon probl=E8me : si je ne d=E9fini pas un
constructeur de copie, la classe devient un peu
dangeureuse. Si je le d=E9fini, n'ai je pas un
probl=E8me de performance important ?
(r=E9allocation / d=E9sallocation "inutiles" au moment
de l'appel de fonction)
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
IR
Manuel Leclerc wrote:
Je voudrais qu'une fonction renvoie un objet encapsulant un pointeur allouée par la fonction, de façon à ce que l'appelant n'ait pas à se soucier de la libération du pointeur : elle sera faite quand l'objet retourné quitera la portée dans l'appelant. [snip]
Il y a une raison précise pour ne pas utiliser std::auto_ptr?
-- IR
Manuel Leclerc wrote:
Je voudrais qu'une fonction renvoie un objet encapsulant
un pointeur allouée par la fonction, de façon à ce que
l'appelant n'ait pas à se soucier de la libération du
pointeur : elle sera faite quand l'objet retourné quitera
la portée dans l'appelant.
[snip]
Il y a une raison précise pour ne pas utiliser std::auto_ptr?
Je voudrais qu'une fonction renvoie un objet encapsulant un pointeur allouée par la fonction, de façon à ce que l'appelant n'ait pas à se soucier de la libération du pointeur : elle sera faite quand l'objet retourné quitera la portée dans l'appelant. [snip]
Il y a une raison précise pour ne pas utiliser std::auto_ptr?
-- IR
Sylvain Togni
Manuel Leclerc wrote:
class class amp { public: void * m_p; amp( void * pAllocated ) : m_p( pAllocated ) {} ~amp() { /* libération de p */ } };
Mon problème : si je ne défini pas un constructeur de copie, la classe devient un peu dangeureuse. Si je le défini, n'ai je pas un problème de performance important ? (réallocation / désallocation "inutiles" au moment de l'appel de fonction)
Regarde du côté de std::auto_ptr ou boost::share_ptr, ils implémentent des mécanismes permettant d'éviter les copies inutiles.
Pour une utilisation en retour de fonction, std::auto_ptr convient, il utilise la notion d'"ownership" pour déterminer quand désallouer l'objet.
-- Sylvain Togni
Manuel Leclerc wrote:
class class amp {
public:
void * m_p;
amp( void * pAllocated ) : m_p( pAllocated ) {}
~amp() { /* libération de p */ }
};
Mon problème : si je ne défini pas un
constructeur de copie, la classe devient un peu
dangeureuse. Si je le défini, n'ai je pas un
problème de performance important ?
(réallocation / désallocation "inutiles" au moment
de l'appel de fonction)
Regarde du côté de std::auto_ptr ou boost::share_ptr, ils
implémentent des mécanismes permettant d'éviter les copies
inutiles.
Pour une utilisation en retour de fonction, std::auto_ptr
convient, il utilise la notion d'"ownership" pour déterminer
quand désallouer l'objet.
Mon problème : si je ne défini pas un constructeur de copie, la classe devient un peu dangeureuse. Si je le défini, n'ai je pas un problème de performance important ? (réallocation / désallocation "inutiles" au moment de l'appel de fonction)
Regarde du côté de std::auto_ptr ou boost::share_ptr, ils implémentent des mécanismes permettant d'éviter les copies inutiles.
Pour une utilisation en retour de fonction, std::auto_ptr convient, il utilise la notion d'"ownership" pour déterminer quand désallouer l'objet.
-- Sylvain Togni
Manuel Leclerc
Il y a une raison précise pour ne pas utiliser std::auto_ptr?
la ressource que j'encapsule n'a pas été allouée avec new...
Mais du coup je me suis demandé comment auto_ptr prenait en compte les histoires de copies et de retour de fonction, et je viens de lire : http://www.awprofessional.com/content/images/020163371X/autoptrupdate%5Caut o_ptr_update.html
Ca fait peur !
Il y a une raison précise pour ne pas utiliser std::auto_ptr?
la ressource que j'encapsule n'a pas été allouée avec new...
Mais du coup je me suis demandé comment auto_ptr prenait
en compte les histoires de copies et de retour de
fonction, et je viens de lire :
http://www.awprofessional.com/content/images/020163371X/autoptrupdate%5Caut o_ptr_update.html
Il y a une raison précise pour ne pas utiliser std::auto_ptr?
la ressource que j'encapsule n'a pas été allouée avec new...
Mais du coup je me suis demandé comment auto_ptr prenait en compte les histoires de copies et de retour de fonction, et je viens de lire : http://www.awprofessional.com/content/images/020163371X/autoptrupdate%5Caut o_ptr_update.html
Ca fait peur !
Sylvain
Manuel Leclerc wrote on 22/11/2006 18:30:
Je voudrais qu'une fonction renvoie un objet encapsulant un pointeur allouée par la fonction, de façon à ce que l'appelant n'ait pas à se soucier de la libération du pointeur : elle sera faite quand l'objet retourné quitera la portée dans l'appelant.
cette "simplicité" pour l'appelant peut être une raison, il peut s'agir également de fournir une facade utilisant une instance interne (m_p) qui est inconnu de amp ou volontairement masquée.
Mon problème : si je ne défini pas un constructeur de copie, la classe devient un peu dangeureuse. Si je le défini, n'ai je pas un problème de performance important ?
dans les 2 cas, un reference counting sur la classe interne sera nécessaire, et cela adresse justement les performances (comme le fait que cette classe interne peut -elle- ne pas supporter la copie).
soit par exemple (je remplace void* par qlq chose de plus expressif)
class class amp { public: // public interface for 'amp' service class iAmp { private: long counter; public: iAmp() { counter = 0; } virtual ~iAmp() {} // referencement long addRef() { return ++counter; } long release() { return --counter; } // service(s) virtual void foo() = null; };
protected: iAmp* m_p; // opaque provider
public: explicit amp(iAmp* p){ // initialisation par iAmp existant if ((m_p = p) != null) m_p->addRef(); } amp(const amp& other){ // un 'amp' est créé, le même iAmp est utilisé if ((m_p = other.m_p) != null) m_p->addRef(); } amp& operator= (const amp& other){ // utilise le iAmp de 'other', libère le précédent si <> iAmp* old = m_p; if ((m_p = other.m_p) != null) m_p->addRef(); if (old) old->release(); return *this; } virtual ~amp(){ // liberation conditionnel du provider if (m_p && m_p->release() == 0) delete m_p; }
// access aux services void foo() { if (m_p) m_p->foo(); } }
notez que l'on détruit (de manière conditionnel) le iAmp dans le destructeur de amp; on pourrait choisir de le faire dans iAmp::release, toutefois si m_p est (vraiment) une classe opaque je préfère cette version, elle évite de plus les risques de destruction alors que la référence existe encore dans des 'amp' (suite à un mauvais décompte).
Sylvain.
Manuel Leclerc wrote on 22/11/2006 18:30:
Je voudrais qu'une fonction renvoie un objet encapsulant
un pointeur allouée par la fonction, de façon à ce que
l'appelant n'ait pas à se soucier de la libération du
pointeur : elle sera faite quand l'objet retourné quitera
la portée dans l'appelant.
cette "simplicité" pour l'appelant peut être une raison, il peut s'agir
également de fournir une facade utilisant une instance interne (m_p) qui
est inconnu de amp ou volontairement masquée.
Mon problème : si je ne défini pas un
constructeur de copie, la classe devient un peu
dangeureuse. Si je le défini, n'ai je pas un
problème de performance important ?
dans les 2 cas, un reference counting sur la classe interne sera
nécessaire, et cela adresse justement les performances (comme le fait
que cette classe interne peut -elle- ne pas supporter la copie).
soit par exemple (je remplace void* par qlq chose de plus expressif)
class class amp {
public:
// public interface for 'amp' service
class iAmp {
private:
long counter;
public:
iAmp() { counter = 0; }
virtual ~iAmp() {}
// referencement
long addRef() { return ++counter; }
long release() { return --counter; }
// service(s)
virtual void foo() = null;
};
protected:
iAmp* m_p; // opaque provider
public:
explicit amp(iAmp* p){
// initialisation par iAmp existant
if ((m_p = p) != null)
m_p->addRef();
}
amp(const amp& other){
// un 'amp' est créé, le même iAmp est utilisé
if ((m_p = other.m_p) != null)
m_p->addRef();
}
amp& operator= (const amp& other){
// utilise le iAmp de 'other', libère le précédent si <>
iAmp* old = m_p;
if ((m_p = other.m_p) != null)
m_p->addRef();
if (old)
old->release();
return *this;
}
virtual ~amp(){
// liberation conditionnel du provider
if (m_p && m_p->release() == 0)
delete m_p;
}
// access aux services
void foo() { if (m_p) m_p->foo(); }
}
notez que l'on détruit (de manière conditionnel) le iAmp dans le
destructeur de amp; on pourrait choisir de le faire dans iAmp::release,
toutefois si m_p est (vraiment) une classe opaque je préfère cette
version, elle évite de plus les risques de destruction alors que la
référence existe encore dans des 'amp' (suite à un mauvais décompte).
Je voudrais qu'une fonction renvoie un objet encapsulant un pointeur allouée par la fonction, de façon à ce que l'appelant n'ait pas à se soucier de la libération du pointeur : elle sera faite quand l'objet retourné quitera la portée dans l'appelant.
cette "simplicité" pour l'appelant peut être une raison, il peut s'agir également de fournir une facade utilisant une instance interne (m_p) qui est inconnu de amp ou volontairement masquée.
Mon problème : si je ne défini pas un constructeur de copie, la classe devient un peu dangeureuse. Si je le défini, n'ai je pas un problème de performance important ?
dans les 2 cas, un reference counting sur la classe interne sera nécessaire, et cela adresse justement les performances (comme le fait que cette classe interne peut -elle- ne pas supporter la copie).
soit par exemple (je remplace void* par qlq chose de plus expressif)
class class amp { public: // public interface for 'amp' service class iAmp { private: long counter; public: iAmp() { counter = 0; } virtual ~iAmp() {} // referencement long addRef() { return ++counter; } long release() { return --counter; } // service(s) virtual void foo() = null; };
protected: iAmp* m_p; // opaque provider
public: explicit amp(iAmp* p){ // initialisation par iAmp existant if ((m_p = p) != null) m_p->addRef(); } amp(const amp& other){ // un 'amp' est créé, le même iAmp est utilisé if ((m_p = other.m_p) != null) m_p->addRef(); } amp& operator= (const amp& other){ // utilise le iAmp de 'other', libère le précédent si <> iAmp* old = m_p; if ((m_p = other.m_p) != null) m_p->addRef(); if (old) old->release(); return *this; } virtual ~amp(){ // liberation conditionnel du provider if (m_p && m_p->release() == 0) delete m_p; }
// access aux services void foo() { if (m_p) m_p->foo(); } }
notez que l'on détruit (de manière conditionnel) le iAmp dans le destructeur de amp; on pourrait choisir de le faire dans iAmp::release, toutefois si m_p est (vraiment) une classe opaque je préfère cette version, elle évite de plus les risques de destruction alors que la référence existe encore dans des 'amp' (suite à un mauvais décompte).
Sylvain.
dieu.tout.puissant
Manuel Leclerc wrote:
class class amp { public: void * m_p; amp( void * pAllocated ) : m_p( pAllocated ) {} ~amp() { /* libération de p */ } };
Mon problème : si je ne défini pas un constructeur de copie, la classe devient un peu dangeureuse. Si je le défini, n'ai je pas un problème de performance important ? (réallocation / désallocation "inutiles" au moment de l'appel de fonction)
Pour le code que tu présentes précisément, la question ne se pose pas. En effet, si ton compilateur dispose des 2 optimisations (très répandues) suivantes : - RVO - optimisation de l'initilisation d'un objet par un objet temporaire
ton code ne fera pas appel à un constructeur de copie (la construction de l'objet retourné "amp" tiendra place directement dans l'espace mémoire alloué à "NoMemoryLeak").
Ensuite, bien entendu, il faut examiner toutes les utilisations potentielles d'objets de type "amp" , mais il ne vaut mieux pas se référer à cette notion de classe "un peu dangereuse", soit elle marche dans tous les cas, soit elle ne marche pas dans certains cas : c'est ce qui commande la décision d'utiliser ou non un mécanisme de réplication d'objets sous-jacents.
Manuel Leclerc wrote:
class class amp {
public:
void * m_p;
amp( void * pAllocated ) : m_p( pAllocated ) {}
~amp() { /* libération de p */ }
};
Mon problème : si je ne défini pas un
constructeur de copie, la classe devient un peu
dangeureuse. Si je le défini, n'ai je pas un
problème de performance important ?
(réallocation / désallocation "inutiles" au moment
de l'appel de fonction)
Pour le code que tu présentes précisément, la question ne se pose
pas. En effet, si ton compilateur dispose des 2 optimisations (très
répandues) suivantes :
- RVO
- optimisation de l'initilisation d'un objet par un objet temporaire
ton code ne fera pas appel à un constructeur de copie (la construction
de l'objet retourné "amp" tiendra place directement dans l'espace
mémoire alloué à "NoMemoryLeak").
Ensuite, bien entendu, il faut examiner toutes les utilisations
potentielles d'objets de type "amp" , mais il ne vaut mieux pas se
référer à cette notion de classe "un peu dangereuse", soit elle
marche dans tous les cas, soit elle ne marche pas dans certains cas :
c'est ce qui commande la décision d'utiliser ou non un mécanisme de
réplication d'objets sous-jacents.
Mon problème : si je ne défini pas un constructeur de copie, la classe devient un peu dangeureuse. Si je le défini, n'ai je pas un problème de performance important ? (réallocation / désallocation "inutiles" au moment de l'appel de fonction)
Pour le code que tu présentes précisément, la question ne se pose pas. En effet, si ton compilateur dispose des 2 optimisations (très répandues) suivantes : - RVO - optimisation de l'initilisation d'un objet par un objet temporaire
ton code ne fera pas appel à un constructeur de copie (la construction de l'objet retourné "amp" tiendra place directement dans l'espace mémoire alloué à "NoMemoryLeak").
Ensuite, bien entendu, il faut examiner toutes les utilisations potentielles d'objets de type "amp" , mais il ne vaut mieux pas se référer à cette notion de classe "un peu dangereuse", soit elle marche dans tous les cas, soit elle ne marche pas dans certains cas : c'est ce qui commande la décision d'utiliser ou non un mécanisme de réplication d'objets sous-jacents.
Sylvain
Manuel Leclerc wrote on 22/11/2006 19:58:
Il y a une raison précise pour ne pas utiliser std::auto_ptr?
la ressource que j'encapsule n'a pas été allouée avec new...
Mais du coup je me suis demandé comment auto_ptr prenait en compte les histoires de copies et de retour de fonction, et je viens de lire :
"l'histoire de la copie" avec std::auto_ptr est simple, il ne copie pas, il transfère la propriété (enfin à ce que j'ai compris).
dès lors si le constructeur de copie (amp(const amp&)) ou l'operateur de copie (operator= (const amp&)) sont utilisés pour effectivement avoir plusieurs instances qui utilisent le même m_p (et non juste répondre à comment est stocké le résultat d'un fonction type "amp f();") alors auto_ptr est inutilisable.
Sylvain.
Manuel Leclerc wrote on 22/11/2006 19:58:
Il y a une raison précise pour ne pas utiliser std::auto_ptr?
la ressource que j'encapsule n'a pas été allouée avec new...
Mais du coup je me suis demandé comment auto_ptr prenait
en compte les histoires de copies et de retour de
fonction, et je viens de lire :
"l'histoire de la copie" avec std::auto_ptr est simple, il ne copie pas,
il transfère la propriété (enfin à ce que j'ai compris).
dès lors si le constructeur de copie (amp(const amp&)) ou l'operateur de
copie (operator= (const amp&)) sont utilisés pour effectivement avoir
plusieurs instances qui utilisent le même m_p (et non juste répondre à
comment est stocké le résultat d'un fonction type "amp f();") alors
auto_ptr est inutilisable.
Il y a une raison précise pour ne pas utiliser std::auto_ptr?
la ressource que j'encapsule n'a pas été allouée avec new...
Mais du coup je me suis demandé comment auto_ptr prenait en compte les histoires de copies et de retour de fonction, et je viens de lire :
"l'histoire de la copie" avec std::auto_ptr est simple, il ne copie pas, il transfère la propriété (enfin à ce que j'ai compris).
dès lors si le constructeur de copie (amp(const amp&)) ou l'operateur de copie (operator= (const amp&)) sont utilisés pour effectivement avoir plusieurs instances qui utilisent le même m_p (et non juste répondre à comment est stocké le résultat d'un fonction type "amp f();") alors auto_ptr est inutilisable.
Sylvain.
Marc G
je comprends pas trop ton problème...mais j'ai 2 remarques : - si la ressource n'a pas été allouée avec new dans le fonction f, alors tu vas avoir de gros problèmes, car tu transmets l'adresse d'un objet détruit... - si ta classe amp n'a qu'une donnée membre de type pointeur, un constructeur de copie ne doit pas être beaucoup moins performant qu'une initialisation directe !
et si auto_ptr ne te convient pas, tu peux bricoler une classe du genre
template <typename U> class Ptr { public :
//======================================================================================== // Constructeurs //======================================================================================== Ptr(U* x) : _ptr(x) {} // prend possession d'un objet U alloué avec new Ptr(U const& x) : _ptr(new U(x)) {} // copie intégrale d'un objet U // transfert de la propriété de l'objet Ptr(Ptr& x) : _ptr(x.reset()) {} // "transfert de propriété" //======================================================================================== ~Ptr() { if (_ptr) delete _ptr;} U* operator->() throw() { return _ptr;} U& operator*() throw() { return *_ptr;} // Opérateur * préfixé U const* operator->() const throw() { return _ptr;} U const& operator*() const throw() { return *_ptr;} // Opérateur * préfixé U* reset(void) { U* old=_ptr; _ptr=NULL; return old;} private : U *_ptr; };
en faisant attention au constructeur que tu utilises, selon ce que tu souhaites ! Bon courage Marc
je comprends pas trop ton problème...mais j'ai 2 remarques :
- si la ressource n'a pas été allouée avec new dans le fonction f, alors tu
vas avoir de gros problèmes, car tu transmets l'adresse d'un objet
détruit...
- si ta classe amp n'a qu'une donnée membre de type pointeur, un
constructeur de copie ne doit pas être beaucoup moins performant qu'une
initialisation directe !
et si auto_ptr ne te convient pas, tu peux bricoler une classe du genre
template <typename U>
class Ptr
{
public :
//======================================================================================== // Constructeurs
//======================================================================================== Ptr(U* x) : _ptr(x) {} //
prend possession d'un objet U alloué avec new
Ptr(U const& x) : _ptr(new U(x)) {} // copie
intégrale d'un objet U
// transfert de la propriété de l'objet
Ptr(Ptr& x) : _ptr(x.reset()) {} //
"transfert de propriété"
//======================================================================================== ~Ptr() { if (_ptr) delete _ptr;}
U* operator->() throw() { return _ptr;}
U& operator*() throw() { return *_ptr;} //
Opérateur * préfixé
U const* operator->() const throw() { return _ptr;}
U const& operator*() const throw() { return *_ptr;} //
Opérateur * préfixé
U* reset(void) { U* old=_ptr; _ptr=NULL; return old;}
private :
U *_ptr;
};
en faisant attention au constructeur que tu utilises, selon ce que tu
souhaites !
Bon courage
Marc
je comprends pas trop ton problème...mais j'ai 2 remarques : - si la ressource n'a pas été allouée avec new dans le fonction f, alors tu vas avoir de gros problèmes, car tu transmets l'adresse d'un objet détruit... - si ta classe amp n'a qu'une donnée membre de type pointeur, un constructeur de copie ne doit pas être beaucoup moins performant qu'une initialisation directe !
et si auto_ptr ne te convient pas, tu peux bricoler une classe du genre
template <typename U> class Ptr { public :
//======================================================================================== // Constructeurs //======================================================================================== Ptr(U* x) : _ptr(x) {} // prend possession d'un objet U alloué avec new Ptr(U const& x) : _ptr(new U(x)) {} // copie intégrale d'un objet U // transfert de la propriété de l'objet Ptr(Ptr& x) : _ptr(x.reset()) {} // "transfert de propriété" //======================================================================================== ~Ptr() { if (_ptr) delete _ptr;} U* operator->() throw() { return _ptr;} U& operator*() throw() { return *_ptr;} // Opérateur * préfixé U const* operator->() const throw() { return _ptr;} U const& operator*() const throw() { return *_ptr;} // Opérateur * préfixé U* reset(void) { U* old=_ptr; _ptr=NULL; return old;} private : U *_ptr; };
en faisant attention au constructeur que tu utilises, selon ce que tu souhaites ! Bon courage Marc
Manuel Leclerc
amp NoMemoryLeak = f();
Pour le code que tu présentes précisément, la question ne se pose pas. En effet, si ton compilateur dispose des 2 optimisations (très répandues) suivantes : - RVO - optimisation de l'initilisation d'un objet par un objet temporaire
ton code ne fera pas appel à un constructeur de copie (la construction de l'objet retourné "amp" tiendra place directement dans l'espace mémoire alloué à "NoMemoryLeak").
Ok. Mon VS2005 n'appelle pas le constructeur de copie en mode release (il le fait en mode debug).
Donc, il va me falloir définir l'opérateur d'affectation.
Ai-je un moyen de savoir que je peux capturer le pointeur présent dans l'objet rendue par la fonction f de manière à éviter une séquence copy/free ?
Autrement dit, puis je définir deux opérateurs d'affectation différents pour les deux cas ci-dessous
A) amp NoMemoryLeak; /* */ NoMemoryLeak = f();
B) amp NoMemoryLeak; amp NoMemoryLeak2; /* */ NoMemoryLeak = NoMemoryLeak2;
Si je ne peux pas, je crois qu'il va falloir que j'utilise l'histoire du comptage de référence proposée par Sylvain, mais j'aurais préféré éviter :-)
amp NoMemoryLeak = f();
Pour le code que tu présentes précisément, la question ne se
pose pas. En effet, si ton compilateur dispose des 2 optimisations
(très répandues) suivantes :
- RVO
- optimisation de l'initilisation d'un objet par un objet temporaire
ton code ne fera pas appel à un constructeur de copie (la construction
de l'objet retourné "amp" tiendra place directement dans l'espace
mémoire alloué à "NoMemoryLeak").
Ok. Mon VS2005 n'appelle pas le constructeur de copie en
mode release (il le fait en mode debug).
Pour le code que tu présentes précisément, la question ne se pose pas. En effet, si ton compilateur dispose des 2 optimisations (très répandues) suivantes : - RVO - optimisation de l'initilisation d'un objet par un objet temporaire
ton code ne fera pas appel à un constructeur de copie (la construction de l'objet retourné "amp" tiendra place directement dans l'espace mémoire alloué à "NoMemoryLeak").
Ok. Mon VS2005 n'appelle pas le constructeur de copie en mode release (il le fait en mode debug).
Donc, il va me falloir définir l'opérateur d'affectation.
Ai-je un moyen de savoir que je peux capturer le pointeur présent dans l'objet rendue par la fonction f de manière à éviter une séquence copy/free ?
Autrement dit, puis je définir deux opérateurs d'affectation différents pour les deux cas ci-dessous
A) amp NoMemoryLeak; /* */ NoMemoryLeak = f();
B) amp NoMemoryLeak; amp NoMemoryLeak2; /* */ NoMemoryLeak = NoMemoryLeak2;
Si je ne peux pas, je crois qu'il va falloir que j'utilise l'histoire du comptage de référence proposée par Sylvain, mais j'aurais préféré éviter :-)
dieu.tout.puissant
On 23 nov, 15:11, "Manuel Leclerc" wrote:
amp NoMemoryLeak = f();
Pour le code que tu présentes précisément, la question ne se pose pas. En effet, si ton compilateur dispose des 2 optimisations (très répandues) suivantes : - RVO - optimisation de l'initilisation d'un objet par un objet temporaire
ton code ne fera pas appel à un constructeur de copie (la construction de l'objet retourné "amp" tiendra place directement dans l'espace mémoire alloué à "NoMemoryLeak").Ok. Mon VS2005 n'appelle pas le constructeur de copie en mode release (il le fait en mode debug).
Donc, il va me falloir définir l'opérateur d'affectation.
Ai-je un moyen de savoir que je peux capturer le pointeur présent dans l'objet rendue par la fonction f de manière à éviter une séquence copy/free ?
Autrement dit, puis je définir deux opérateurs d'affectation différents pour les deux cas ci-dessous
A) amp NoMemoryLeak; /* */ NoMemoryLeak = f();
B) amp NoMemoryLeak; amp NoMemoryLeak2; /* */ NoMemoryLeak = NoMemoryLeak2;
Si je ne peux pas, je crois qu'il va falloir que j'utilise l'histoire du comptage de référence proposée par Sylvain, mais j'aurais préféré éviter :-)
Désolé :) mais d'après ces cas d'utilisation, le comptage de référence est le bon choix. Puisque tu as l'air de vouloir éviter au maximum les copies non nécessaires, il te faut un mécanisme de Copy-on-Write. Le comptage de référence est le mécanisme le plus simple implémentant un CoW.
On 23 nov, 15:11, "Manuel Leclerc" <manuel.lecl...@alussinan.org>
wrote:
amp NoMemoryLeak = f();
Pour le code que tu présentes précisément, la question ne se
pose pas. En effet, si ton compilateur dispose des 2 optimisations
(très répandues) suivantes :
- RVO
- optimisation de l'initilisation d'un objet par un objet temporaire
ton code ne fera pas appel à un constructeur de copie (la construction
de l'objet retourné "amp" tiendra place directement dans l'espace
mémoire alloué à "NoMemoryLeak").Ok. Mon VS2005 n'appelle pas le constructeur de copie en
mode release (il le fait en mode debug).
Donc, il va me falloir définir l'opérateur d'affectation.
Ai-je un moyen de savoir que je peux capturer
le pointeur présent dans l'objet rendue par la
fonction f de manière à éviter une séquence
copy/free ?
Autrement dit, puis je définir deux opérateurs
d'affectation différents pour les deux cas ci-dessous
A)
amp NoMemoryLeak;
/* */
NoMemoryLeak = f();
B)
amp NoMemoryLeak;
amp NoMemoryLeak2;
/* */
NoMemoryLeak = NoMemoryLeak2;
Si je ne peux pas, je crois qu'il va falloir que j'utilise
l'histoire du comptage de référence proposée par
Sylvain, mais j'aurais préféré éviter :-)
Désolé :) mais d'après ces cas d'utilisation, le comptage de
référence est le bon choix. Puisque tu as l'air de vouloir éviter au
maximum les copies non nécessaires, il te faut un mécanisme de
Copy-on-Write. Le comptage de référence est le mécanisme le plus
simple implémentant un CoW.
Pour le code que tu présentes précisément, la question ne se pose pas. En effet, si ton compilateur dispose des 2 optimisations (très répandues) suivantes : - RVO - optimisation de l'initilisation d'un objet par un objet temporaire
ton code ne fera pas appel à un constructeur de copie (la construction de l'objet retourné "amp" tiendra place directement dans l'espace mémoire alloué à "NoMemoryLeak").Ok. Mon VS2005 n'appelle pas le constructeur de copie en mode release (il le fait en mode debug).
Donc, il va me falloir définir l'opérateur d'affectation.
Ai-je un moyen de savoir que je peux capturer le pointeur présent dans l'objet rendue par la fonction f de manière à éviter une séquence copy/free ?
Autrement dit, puis je définir deux opérateurs d'affectation différents pour les deux cas ci-dessous
A) amp NoMemoryLeak; /* */ NoMemoryLeak = f();
B) amp NoMemoryLeak; amp NoMemoryLeak2; /* */ NoMemoryLeak = NoMemoryLeak2;
Si je ne peux pas, je crois qu'il va falloir que j'utilise l'histoire du comptage de référence proposée par Sylvain, mais j'aurais préféré éviter :-)
Désolé :) mais d'après ces cas d'utilisation, le comptage de référence est le bon choix. Puisque tu as l'air de vouloir éviter au maximum les copies non nécessaires, il te faut un mécanisme de Copy-on-Write. Le comptage de référence est le mécanisme le plus simple implémentant un CoW.