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

element d'un vector detruit par un autre objet

8 réponses
Avatar
korchkidu
Bonjour a tous,

j'ai une classe B qui contient un std::vector<A*> _A.
La classe A contient (pour l'exemple) une seule methode A::detach() qui
est chargee de se chercher dans B et d'effacer l'element correspondant
(et de faire tous pleins d'autres super...;) ).

Dans le destructeur de B, je dois appeler detach() sur chaque objet.

Je fais un truc du genre:

A *current_A;

int size = _A.size();
int i;

for (i=0;i<size;++i)
{
current_A = _A.front();
current_A->detach(); //efface current_A de _A
}

Mais je ne sais pas pourquoi, je sens que derriere ca ya un truc qui
m'echappe et qui fait que ca a la couleur d'un truc qui marche, l'odeur
d'un truc qui marche, mais ca marche pas en vrai...
Ya t-il des gens parmi vous pour me dire si ca marche ca?..;)

Merci,
K.

8 réponses

Avatar
Vianney Lançon
On 2004-11-15, korchkidu wrote:
Bonjour a tous,

j'ai une classe B qui contient un std::vector<A*> _A.
La classe A contient (pour l'exemple) une seule methode A::detach() qui
est chargee de se chercher dans B et d'effacer l'element correspondant
(et de faire tous pleins d'autres super...;) ).

Dans le destructeur de B, je dois appeler detach() sur chaque objet.

Je fais un truc du genre:

A *current_A;

int size = _A.size();
int i;

for (i=0;i<size;++i)
{
current_A = _A.front();
current_A->detach(); //efface current_A de _A
}


Si current_A->detach() modifie la taille de A_, tu as un problème.
Car la size a une valeur constantante.


while (!_A.empty())
{
A* current_A = _A.front();
current_A->detach(); // enleve current_A de _A
}

Avatar
Alexandre
bonjour,

j'ai une classe B qui contient un std::vector<A*> _A.

La classe A contient (pour l'exemple) une seule methode A::detach() qui
est chargee de se chercher dans B et d'effacer l'element correspondant (et
de faire tous pleins d'autres super...;) ).


étrange que la méthode de A supprime l'élement dans le vecteur de B...


Dans le destructeur de B, je dois appeler detach() sur chaque objet.

Je fais un truc du genre:

A *current_A;

int size = _A.size();
int i;

for (i=0;i<size;++i)
{
current_A = _A.front();
current_A->detach(); //efface current_A de _A
}

Mais je ne sais pas pourquoi, je sens que derriere ca ya un truc qui
m'echappe et qui fait que ca a la couleur d'un truc qui marche, l'odeur
d'un truc qui marche, mais ca marche pas en vrai...
Ya t-il des gens parmi vous pour me dire si ca marche ca?..;)


ben ça dépend de ce que fait la méthode detach(). Elle a accès à _A ?
Comment ?


Merci,
K.


Avatar
korchkidu
Vianney Lançon wrote:
On 2004-11-15, korchkidu wrote:

Bonjour a tous,

j'ai une classe B qui contient un std::vector<A*> _A.
La classe A contient (pour l'exemple) une seule methode A::detach() qui
est chargee de se chercher dans B et d'effacer l'element correspondant
(et de faire tous pleins d'autres super...;) ).

Dans le destructeur de B, je dois appeler detach() sur chaque objet.

Je fais un truc du genre:

A *current_A;

int size = _A.size();
int i;

for (i=0;i<size;++i)
{
current_A = _A.front();
current_A->detach(); //efface current_A de _A
}



Si current_A->detach() modifie la taille de A_, tu as un problème.
Car la size a une valeur constantante.
Ah bah oui forcement. Ca parait logique...


Merci,
K.


Avatar
kanze
korchkidu wrote in message
news:<4198d8c9$...

j'ai une classe B qui contient un std::vector<A*> _A. La classe A
contient (pour l'exemple) une seule methode A::detach() qui est
chargee de se chercher dans B et d'effacer l'element correspondant (et
de faire tous pleins d'autres super...;) ).

Dans le destructeur de B, je dois appeler detach() sur chaque objet.

Je fais un truc du genre:

A *current_A;

int size = _A.size();
int i;

for (i=0;i<size;++i)
{
current_A = _A.front();
current_A->detach(); //efface current_A de _A
}

Mais je ne sais pas pourquoi, je sens que derriere ca ya un truc qui
m'echappe et qui fait que ca a la couleur d'un truc qui marche,
l'odeur d'un truc qui marche, mais ca marche pas en vrai... Ya t-il
des gens parmi vous pour me dire si ca marche ca?..;)


Tel quel, ça marche, mais...

Si pour une raison quelconque, tu modifies le code de façon à ce que le
detach() d'un A enlève en fait plusieurs A du B, ça ne marchera
plus. AMHA, mieux vaut :

while ( ! _A.empty() ) {
_A.front()->detach() ;
}

Deux autres commentaires :

- Les noms qui commencent par un _ sont à éviter. Les noms qui
commencent par un _ suivi d'un majuscule sont carrément interdits
par le langage.

- En général, en C++, on évite de declarer des variables avant qu'on
en a besoin, sans initialisation. Dans ton cas, la variable
current_A, n'est même pas nécessaire, mais si tu veux le garder,
pour des raisons de lisibilité ou d'autre (je trouve la version sans
variable tout à fait lisible, mais des avis peuvent varier), il
serait préférable de la définir directement dans la boucle, avec
l'initialisation qu'il faut :

while ( ! myA.empty() ) {
A* currentA = myA.front() ;
// ...
}

--
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
kanze
"Alexandre" wrote in message
news:<4198f1c2$0$10457$...

j'ai une classe B qui contient un std::vector<A*> _A.

La classe A contient (pour l'exemple) une seule methode A::detach()
qui est chargee de se chercher dans B et d'effacer l'element
correspondant (et de faire tous pleins d'autres super...;) ).


étrange que la méthode de A supprime l'élement dans le vecteur de B...


Des registries ne sont pas si rares que ça. Je suppose que dans son
code, les noms sont plutôt de genre EventDispatcher et EventHandler, par
exemple. C'est un idiome connu, et même assez courant.

Dans le destructeur de B, je dois appeler detach() sur chaque objet.

Je fais un truc du genre:

A *current_A;

int size = _A.size();
int i;

for (i=0;i<size;++i)
{
current_A = _A.front();
current_A->detach(); //efface current_A de _A
}

Mais je ne sais pas pourquoi, je sens que derriere ca ya un truc qui
m'echappe et qui fait que ca a la couleur d'un truc qui marche,
l'odeur d'un truc qui marche, mais ca marche pas en vrai... Ya t-il
des gens parmi vous pour me dire si ca marche ca?..;)


ben ça dépend de ce que fait la méthode detach(). Elle a accès à _A ?
Comment ?


À _A, probablement pas. Mais à B, pourquoi pas ? (J'avoue que je n'aime
pas trop l'idée qu'on accède à B de dehors lorsqu'on est dans le
destructeur de B. Mais dans ce cas-ci, il me semble justifier. À
condition qu'on ne dérive pas de B.)

--
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
korchkidu
wrote:

Deux autres commentaires :

- Les noms qui commencent par un _ sont à éviter.
Bah mes attributs prives sont declares de la sorte. Je trouve ca plutot

pratique en fait. Ca me permet de voir directement les membres des
variables normales. Vous faites comment vous?

Les noms qui
commencent par un _ suivi d'un majuscule sont carrément interdits
par le langage.
C'est bon a savoir ca.


- En général, en C++, on évite de declarer des variables avant qu'on
en a besoin, sans initialisation. Dans ton cas, la variable
current_A, n'est même pas nécessaire, mais si tu veux le garder,
pour des raisons de lisibilité ou d'autre (je trouve la version sans
variable tout à fait lisible, mais des avis peuvent varier), il
serait préférable de la définir directement dans la boucle, avec
l'initialisation qu'il faut :

while ( ! myA.empty() ) {
A* currentA = myA.front() ;
// ...
}
Je vois. C'est marrant mais je croyais qu'il valait mieux declarer les

variables en dehors des boucles. Si on les met dans une boucle, ca va en
creer une a chaque fois non?

Avatar
kanze
korchkidu wrote in message
news:<4199edb7$...
wrote:

Deux autres commentaires :

- Les noms qui commencent par un _ sont à éviter.


Bah mes attributs prives sont declares de la sorte. Je trouve ca
plutot pratique en fait. Ca me permet de voir directement les membres
des variables normales. Vous faites comment vous?


Je fais ce que fait mon client:-). En fait, j'ai déjà vu pas mal de
conventions :

- On met un _ à la fin. (Personellement, je n'aime pas. Je le trouve
laid. Aussi, je préfère que l'indication vient en tête. Mais si
c'est la convention chez le client...)

- On utilise un préfixe plus ou moins signifant. Dans la première
boîte où j'ai fait du C++, c'était « the », mais je suis arrivé à
préférer « my » et « our » -- « our » pour les statiques, qui
appartiennent aux tous les objets du type.

- On utilise un préfixe « synthétique » ; dans la dernière boîte où
j'étais, « m_ », avec « s_ » pour les statiques. La plupart du
temps, ça lit moins bien que « my » et « our », mais ça évite des
choses comme « myIsEnabled », etc. (En fait, tel que je l'utilise,
le « my » est aussi un préfixe synthétique. Mais il donne
l'impression de ne pas l'être.)

- On n'utilise rien sur les membres, mais on marque les paramètres.
Soit avec un préfixe synthétique (du genre « p_ », ou simplement
« p »), soit avec une préfixe soi-disant sémantique (l'article
indéfini « a » ou « an » à la Dresdner Bank).

- On n'utilise rien ; on démande plutôt des noms assez significatifs
pour que le problème ne se pose pas. Donc, par exemple, plutôt que
le membre « myState », avec un paramètre « state »,
« currentState », avec un paramèter « newState ».

En principe, je dirais que c'est cette dernière solution qui devait
servir. Mais dans la pratique...

Les noms qui
commencent par un _ suivi d'un majuscule sont carrément interdits
par le langage.


C'est bon a savoir ca.


Dans la pratique, il faut dire que les implémentations ont une tendance
à définir aussi des macros avec _ et une minuscule, ou avec toutes les
lettres majuscules dans leurs en-têtes. Ce sont donc des symboles à
éviter dans le code utilisateur, même si formellement, on en a droit.

- En général, en C++, on évite de declarer des variables avant qu'on
en a besoin, sans initialisation. Dans ton cas, la variable
current_A, n'est même pas nécessaire, mais si tu veux le garder,
pour des raisons de lisibilité ou d'autre (je trouve la version sans
variable tout à fait lisible, mais des avis peuvent varier), il
serait préférable de la définir directement dans la boucle, avec
l'initialisation qu'il faut :

while ( ! myA.empty() ) {
A* currentA = myA.front() ;
// ...
}


Je vois. C'est marrant mais je croyais qu'il valait mieux declarer les
variables en dehors des boucles. Si on les met dans une boucle, ca va
en creer une a chaque fois non?


Oui, et...

En fait, qu'est-ce que tu entends par « créer ». La création d'un objet
en C++ consiste en deux choses, l'allocation de la mémoire, et
l'initialisation (appel du constructeur). Or, dans la pratique, tous les
compilateurs que j'ai jamais vu allouent toute la mémoire qu'il leur
faut pour toutes les variables locales en tête de la fonction. Même si
la variable n'est définie que dans un bloc interne. Il vont donc
réutiliser la même mémoire, sans nouvelle allocation, chaque fois dans
la boucle.

Quant à l'initialisation... Ici, il s'agit d'un pointeur.
L'initialisation coûte exactement comme une affectation. C'est le cas de
tous les types non classe et non tableau, en fait. Alors, il ne peut y
avoir une différence que dans le cas des types de classe. Et là, c'est
loin d'être évident ce qui est plus rapide : affectation ou
destruction/construction. Pour peu que le type essaie de se comporter
bien en face des exceptions, c'est même souvent que l'affectation serait
plus chère.

En tout cas, sauf des cas exceptionnels, la différence est rarement
mésurable. Et tant que le profiler n'en a pas montré la nécessité,
j'écris le code de la manière la plus lisible possible.

--
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
drkm
writes:

- On utilise un préfixe « synthétique » ; dans la dernière boîte où
j'étais, « m_ », avec « s_ » pour les statiques. La plupart du
temps, ça lit moins bien que « my » et « our », mais ça évite des
choses comme « myIsEnabled », etc. (En fait, tel que je l'utilise,
le « my » est aussi un préfixe synthétique. Mais il donne
l'impression de ne pas l'être.)


Et a l'avantage, selon moi, de se lire et se prononcer plus
facilement, plus naturellement. Je préfère « my is enabled » à « èm_
is enabled ».

Mais j'utilise également cette convention. Je ne suis donc pas très
objectif.

--drkm