int main()
{
bool bar = true;
//Ici bar est vrai
{ Foo(bar); /* Ici bar est faux */ }
//Ici bar est vrai
}
Très bien... Maintenant je suis dans la situation où j'ai un tableau de bar
et je veux qu'ils soient tous mis dans un état temporaire pendant un certain
temps. Il serait très pratique de pouvoir faire
std::vector<Foo> foos;
for(std::vector<bool>::const_iterator it = bars.begin(), end = bars.end();
it != end; ++it)
foos.push_back(Foo(*it));
Malheureusement ca ne fonctionne pas tout à fait comme prévu parceque les
instances de foo vont être copiées, et on n'aura pas le même nombre de
constructeur par défaut et de destructeurs (parcequ'il y a les constructeurs
par copie)...
Un possibilité serait de passer par un pointeur intelligent mais je voudrais
éviter de faire trop d'allocation de mémoire pour un truc aussi trivial.
Comment peut-on appliquer le RAII dans ce cas ?
Je suppose qu'ici, le type est en fait bool&. Sinon, je ne vois pas l'intérêt de la classe.
};
int main() { bool bar = true; //Ici bar est vrai { Foo(bar); /* Ici bar est faux */ } //Ici bar est vrai }
Très bien... Maintenant je suis dans la situation où j'ai un tableau de bar et je veux qu'ils soient tous mis dans un état temporaire pendant un certain temps. Il serait très pratique de pouvoir faire
std::vector<Foo> foos; for(std::vector<bool>::const_iterator it = bars.begin(), end = bars.e nd(); it != end; ++it) foos.push_back(Foo(*it));
Malheureusement ca ne fonctionne pas tout à fait comme prévu parceque les instances de foo vont être copiées, et on n'aura pas le même nombre de constructeur par défaut et de destructeurs (parcequ'il y a les constructeurs par copie)...
Un possibilité serait de passer par un pointeur intelligent mais je voudrais éviter de faire trop d'allocation de mémoire pour un truc aussi trivial. Comment peut-on appliquer le RAII dans ce cas ?
Je le fais, mais j'ai bien une allocation mémoire. Étant donné que plusieurs objets, de durée de vie différente, doivent partager un état, je ne vois pas d'autre solution. En revanche, l'état partagé, c'est le compteur d'instance. Un int. Vue que c'est toujours d'une taille fixe, on peut se servir d'un allocateur spécialisé.
(Dans mon cas, je ne le fais pas, parce que les objets en question font des entrées/sorties, et une allocation de plus ou de moins ne va pas changer grand chose.)
C'est en fait beaucoup la logique de boost::shared_ptr. Mais sans l'objet qu'il gère. Et en fait, tu pourrais te servir de boost::shared_ptr directement, avec quelque chose comme :
// ... std::vector< boost::shared_ptr< bool > > foos ; for ( std::deque< bool >::iterator it = bars.begin() ; it != bars.end() ; ++ it ) { *it = false ; foos.push_back( boost::shared_ptr< bool >( &*it, Resetter() ) ) ; }
(Tu remarqueras que je me suis servi de deque pour le tableau de bool. std::vector<bool> ne marche pas, parce que ce n'est pas une séquence au sens de la STL. Mais je suppose que ton utilisation de bool n'est qu'à titre d'exemple, et qu'en fait, il s'agit de tes propres classes.)
Est-ce meilleur que ma première solution ? C'est bien moins de code. En revanche, c'est peut-être un peu subtile pour certains, et dans l'implémentation actuelle, je ne crois pas que boost::shared_ptr utilise un allocateur dédié pour ses compteurs ; il y aura donc bien une allocation et une libération par élément. N'empèche qu'il me plaît bien. (J'avais déjà pens é à quelque chose de semblable pour la gestion des locks de mutex dans un singleton.)
-- James Kanze GABI Software 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
Vincent Lascaux wrote:
J'ai un objet que je veux mettre dans un état temporaire. Pour
celà, j'utilise l'idiome RAII :
Je suppose qu'ici, le type est en fait bool&. Sinon, je ne vois
pas l'intérêt de la classe.
};
int main()
{
bool bar = true;
//Ici bar est vrai
{ Foo(bar); /* Ici bar est faux */ }
//Ici bar est vrai
}
Très bien... Maintenant je suis dans la situation où j'ai un
tableau de bar et je veux qu'ils soient tous mis dans un état
temporaire pendant un certain temps. Il serait très pratique
de pouvoir faire
std::vector<Foo> foos;
for(std::vector<bool>::const_iterator it = bars.begin(), end = bars.e nd();
it != end; ++it)
foos.push_back(Foo(*it));
Malheureusement ca ne fonctionne pas tout à fait comme prévu
parceque les instances de foo vont être copiées, et on n'aura
pas le même nombre de constructeur par défaut et de
destructeurs (parcequ'il y a les constructeurs par copie)...
Un possibilité serait de passer par un pointeur intelligent
mais je voudrais éviter de faire trop d'allocation de mémoire
pour un truc aussi trivial. Comment peut-on appliquer le RAII
dans ce cas ?
Je le fais, mais j'ai bien une allocation mémoire. Étant donné
que plusieurs objets, de durée de vie différente, doivent
partager un état, je ne vois pas d'autre solution. En revanche,
l'état partagé, c'est le compteur d'instance. Un int. Vue que
c'est toujours d'une taille fixe, on peut se servir d'un
allocateur spécialisé.
(Dans mon cas, je ne le fais pas, parce que les objets en
question font des entrées/sorties, et une allocation de plus ou
de moins ne va pas changer grand chose.)
C'est en fait beaucoup la logique de boost::shared_ptr. Mais
sans l'objet qu'il gère. Et en fait, tu pourrais te servir de
boost::shared_ptr directement, avec quelque chose comme :
// ...
std::vector< boost::shared_ptr< bool > >
foos ;
for ( std::deque< bool >::iterator it = bars.begin() ;
it != bars.end() ;
++ it ) {
*it = false ;
foos.push_back( boost::shared_ptr< bool >( &*it, Resetter() ) )
;
}
(Tu remarqueras que je me suis servi de deque pour le tableau de
bool. std::vector<bool> ne marche pas, parce que ce n'est pas
une séquence au sens de la STL. Mais je suppose que ton
utilisation de bool n'est qu'à titre d'exemple, et qu'en fait,
il s'agit de tes propres classes.)
Est-ce meilleur que ma première solution ? C'est bien moins de
code. En revanche, c'est peut-être un peu subtile pour certains,
et dans l'implémentation actuelle, je ne crois pas que
boost::shared_ptr utilise un allocateur dédié pour ses
compteurs ; il y aura donc bien une allocation et une libération
par élément. N'empèche qu'il me plaît bien. (J'avais déjà pens é
à quelque chose de semblable pour la gestion des locks de mutex
dans un singleton.)
--
James Kanze GABI Software
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
Je suppose qu'ici, le type est en fait bool&. Sinon, je ne vois pas l'intérêt de la classe.
};
int main() { bool bar = true; //Ici bar est vrai { Foo(bar); /* Ici bar est faux */ } //Ici bar est vrai }
Très bien... Maintenant je suis dans la situation où j'ai un tableau de bar et je veux qu'ils soient tous mis dans un état temporaire pendant un certain temps. Il serait très pratique de pouvoir faire
std::vector<Foo> foos; for(std::vector<bool>::const_iterator it = bars.begin(), end = bars.e nd(); it != end; ++it) foos.push_back(Foo(*it));
Malheureusement ca ne fonctionne pas tout à fait comme prévu parceque les instances de foo vont être copiées, et on n'aura pas le même nombre de constructeur par défaut et de destructeurs (parcequ'il y a les constructeurs par copie)...
Un possibilité serait de passer par un pointeur intelligent mais je voudrais éviter de faire trop d'allocation de mémoire pour un truc aussi trivial. Comment peut-on appliquer le RAII dans ce cas ?
Je le fais, mais j'ai bien une allocation mémoire. Étant donné que plusieurs objets, de durée de vie différente, doivent partager un état, je ne vois pas d'autre solution. En revanche, l'état partagé, c'est le compteur d'instance. Un int. Vue que c'est toujours d'une taille fixe, on peut se servir d'un allocateur spécialisé.
(Dans mon cas, je ne le fais pas, parce que les objets en question font des entrées/sorties, et une allocation de plus ou de moins ne va pas changer grand chose.)
C'est en fait beaucoup la logique de boost::shared_ptr. Mais sans l'objet qu'il gère. Et en fait, tu pourrais te servir de boost::shared_ptr directement, avec quelque chose comme :
// ... std::vector< boost::shared_ptr< bool > > foos ; for ( std::deque< bool >::iterator it = bars.begin() ; it != bars.end() ; ++ it ) { *it = false ; foos.push_back( boost::shared_ptr< bool >( &*it, Resetter() ) ) ; }
(Tu remarqueras que je me suis servi de deque pour le tableau de bool. std::vector<bool> ne marche pas, parce que ce n'est pas une séquence au sens de la STL. Mais je suppose que ton utilisation de bool n'est qu'à titre d'exemple, et qu'en fait, il s'agit de tes propres classes.)
Est-ce meilleur que ma première solution ? C'est bien moins de code. En revanche, c'est peut-être un peu subtile pour certains, et dans l'implémentation actuelle, je ne crois pas que boost::shared_ptr utilise un allocateur dédié pour ses compteurs ; il y aura donc bien une allocation et une libération par élément. N'empèche qu'il me plaît bien. (J'avais déjà pens é à quelque chose de semblable pour la gestion des locks de mutex dans un singleton.)
-- James Kanze GABI Software 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
JBB
Vincent Lascaux wrote:
Bonjour,
J'ai un objet que je veux mettre dans un état temporaire. Pour celà, j'utilise l'idiome RAII :
class Foo { public: Foo(bool& bar) : m_bar(bar) { m_bar = false; } ~Foo() { m_bar = true; } private: bool m_bar; a mon avis il faut aussi garder une référence sur 'bar' si tu veux
pouvoir changer sa valeur. Par ce qu'ici le 'm_bar = true;' dans le destructeur n'a aucun interêt. De même que le 'm_bar = false' dans le constructeur d'ailleurs vu que m_bar est private.
};
int main() { bool bar = true; //Ici bar est vrai { Foo(bar); /* Ici bar est faux */ } verifie ton code mais ca ne doit pas marcher vraiment
//Ici bar est vrai }
Très bien... Maintenant je suis dans la situation où j'ai un tableau de bar et je veux qu'ils soient tous mis dans un état temporaire pendant un certain temps. Il serait très pratique de pouvoir faire
std::vector<Foo> foos; for(std::vector<bool>::const_iterator it = bars.begin(), end = bars.end(); it != end; ++it) foos.push_back(Foo(*it));
Malheureusement ca ne fonctionne pas tout à fait comme prévu parceque les instances de foo vont être copiées, et on n'aura pas le même nombre de constructeur par défaut et de destructeurs (parcequ'il y a les constructeurs par copie)... Un possibilité serait de passer par un pointeur intelligent mais je voudrais éviter de faire trop d'allocation de mémoire pour un truc aussi trivial. Comment peut-on appliquer le RAII dans ce cas ?
Il suffit de faire pareil avec une classe Foo qui pends en constructeur
une reference sur ton tableau de bool. Il faut alors stocker cette reference ainsi qu'un tableau contenant des copies de toutes les valeurs initiales de ce tableau, afin de pouvoir les remettre dans le destructeur.
Merci
Vincent Lascaux wrote:
Bonjour,
J'ai un objet que je veux mettre dans un état temporaire. Pour celà,
j'utilise l'idiome RAII :
class Foo
{
public:
Foo(bool& bar) : m_bar(bar) { m_bar = false; }
~Foo() { m_bar = true; }
private:
bool m_bar;
a mon avis il faut aussi garder une référence sur 'bar' si tu veux
pouvoir changer sa valeur. Par ce qu'ici le 'm_bar = true;' dans le
destructeur n'a aucun interêt. De même que le 'm_bar = false' dans le
constructeur d'ailleurs vu que m_bar est private.
};
int main()
{
bool bar = true;
//Ici bar est vrai
{ Foo(bar); /* Ici bar est faux */ }
verifie ton code mais ca ne doit pas marcher vraiment
//Ici bar est vrai
}
Très bien... Maintenant je suis dans la situation où j'ai un tableau de bar
et je veux qu'ils soient tous mis dans un état temporaire pendant un certain
temps. Il serait très pratique de pouvoir faire
std::vector<Foo> foos;
for(std::vector<bool>::const_iterator it = bars.begin(), end = bars.end();
it != end; ++it)
foos.push_back(Foo(*it));
Malheureusement ca ne fonctionne pas tout à fait comme prévu parceque les
instances de foo vont être copiées, et on n'aura pas le même nombre de
constructeur par défaut et de destructeurs (parcequ'il y a les constructeurs
par copie)...
Un possibilité serait de passer par un pointeur intelligent mais je voudrais
éviter de faire trop d'allocation de mémoire pour un truc aussi trivial.
Comment peut-on appliquer le RAII dans ce cas ?
Il suffit de faire pareil avec une classe Foo qui pends en constructeur
une reference sur ton tableau de bool.
Il faut alors stocker cette reference ainsi qu'un tableau contenant des
copies de toutes les valeurs initiales de ce tableau, afin de pouvoir
les remettre dans le destructeur.
J'ai un objet que je veux mettre dans un état temporaire. Pour celà, j'utilise l'idiome RAII :
class Foo { public: Foo(bool& bar) : m_bar(bar) { m_bar = false; } ~Foo() { m_bar = true; } private: bool m_bar; a mon avis il faut aussi garder une référence sur 'bar' si tu veux
pouvoir changer sa valeur. Par ce qu'ici le 'm_bar = true;' dans le destructeur n'a aucun interêt. De même que le 'm_bar = false' dans le constructeur d'ailleurs vu que m_bar est private.
};
int main() { bool bar = true; //Ici bar est vrai { Foo(bar); /* Ici bar est faux */ } verifie ton code mais ca ne doit pas marcher vraiment
//Ici bar est vrai }
Très bien... Maintenant je suis dans la situation où j'ai un tableau de bar et je veux qu'ils soient tous mis dans un état temporaire pendant un certain temps. Il serait très pratique de pouvoir faire
std::vector<Foo> foos; for(std::vector<bool>::const_iterator it = bars.begin(), end = bars.end(); it != end; ++it) foos.push_back(Foo(*it));
Malheureusement ca ne fonctionne pas tout à fait comme prévu parceque les instances de foo vont être copiées, et on n'aura pas le même nombre de constructeur par défaut et de destructeurs (parcequ'il y a les constructeurs par copie)... Un possibilité serait de passer par un pointeur intelligent mais je voudrais éviter de faire trop d'allocation de mémoire pour un truc aussi trivial. Comment peut-on appliquer le RAII dans ce cas ?
Il suffit de faire pareil avec une classe Foo qui pends en constructeur
une reference sur ton tableau de bool. Il faut alors stocker cette reference ainsi qu'un tableau contenant des copies de toutes les valeurs initiales de ce tableau, afin de pouvoir les remettre dans le destructeur.