J'aimerai savoir si pour supporter n'importe quel container il faut que je
fasse une surcharge par container, ou bien si en passant par les template
ça peut se faire, mais j'avoue être un peu charette là dessus...
Dans l'ordre, c'est affectation puis incrémentation?
Oui.
En cherchant un peu : http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/stl__algo_8h-source.html#l00778
Tu verras que l'implémentation de libstdc++ ne correspond pas tout à fait à celle que j'ai indiquée.
J'imagine que c'est l'inverse si on choisit une pré-incrémentation?
Oui.
xavier
kanze
xavier wrote:
Michael a dit le 18/01/2005 11:47:
Pourquoi passer une référence de pointeur à delete_ptr et pas le pointeur directement? Le comportement indéfini auquel tu fais allusion en est-il la seule explication?
Pour pouvoir modifier la valeur du pointeur dans le conteneur, il faut le passer par référence.
Par contre, j'aimerais savoir en quoi un pointeur invalide dans un conteneur est un comportement indéfini. A priori, je pensais que le conteneur lui-même ne pouvait manipuler que les pointeurs, et pas les déréférencer... La manipulation de pointeur invalide est-elle un comportement indéfini, tout simplement, ou y a-t-il une raison plus complexe ?
À peu près tout ce que on peut faire avec un pointeur invalide, c'est de lui affecter une nouvelle valeur. Même lire simplement le pointeur est un comportement indéfini. En termes de la norme, on ne peut pas le copier, et la norme dit qu'il faut que tous les éléments dans une collection standard soient copiables.
Dans la pratique, c'est fort peu probable que tu aurais des problèmes.
-- 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
xavier wrote:
Michael a dit le 18/01/2005 11:47:
Pourquoi passer une référence de pointeur à delete_ptr et
pas le pointeur directement? Le comportement indéfini auquel
tu fais allusion en est-il la seule explication?
Pour pouvoir modifier la valeur du pointeur dans le conteneur,
il faut le passer par référence.
Par contre, j'aimerais savoir en quoi un pointeur invalide
dans un conteneur est un comportement indéfini. A priori, je
pensais que le conteneur lui-même ne pouvait manipuler que les
pointeurs, et pas les déréférencer... La manipulation de
pointeur invalide est-elle un comportement indéfini, tout
simplement, ou y a-t-il une raison plus complexe ?
À peu près tout ce que on peut faire avec un pointeur invalide,
c'est de lui affecter une nouvelle valeur. Même lire simplement
le pointeur est un comportement indéfini. En termes de la norme,
on ne peut pas le copier, et la norme dit qu'il faut que tous
les éléments dans une collection standard soient copiables.
Dans la pratique, c'est fort peu probable que tu aurais des
problèmes.
--
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
Pourquoi passer une référence de pointeur à delete_ptr et pas le pointeur directement? Le comportement indéfini auquel tu fais allusion en est-il la seule explication?
Pour pouvoir modifier la valeur du pointeur dans le conteneur, il faut le passer par référence.
Par contre, j'aimerais savoir en quoi un pointeur invalide dans un conteneur est un comportement indéfini. A priori, je pensais que le conteneur lui-même ne pouvait manipuler que les pointeurs, et pas les déréférencer... La manipulation de pointeur invalide est-elle un comportement indéfini, tout simplement, ou y a-t-il une raison plus complexe ?
À peu près tout ce que on peut faire avec un pointeur invalide, c'est de lui affecter une nouvelle valeur. Même lire simplement le pointeur est un comportement indéfini. En termes de la norme, on ne peut pas le copier, et la norme dit qu'il faut que tous les éléments dans une collection standard soient copiables.
Dans la pratique, c'est fort peu probable que tu aurais des problèmes.
-- 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
xavier
a dit le 18/01/2005 16:10:
À peu près tout ce que on peut faire avec un pointeur invalide, c'est de lui affecter une nouvelle valeur. Même lire simplement le pointeur est un comportement indéfini. En termes de la norme, on ne peut pas le copier, et la norme dit qu'il faut que tous les éléments dans une collection standard soient copiables.
Merci pour cette clarification.
xavier
kanze@gabi-soft.fr a dit le 18/01/2005 16:10:
À peu près tout ce que on peut faire avec un pointeur invalide,
c'est de lui affecter une nouvelle valeur. Même lire simplement
le pointeur est un comportement indéfini. En termes de la norme,
on ne peut pas le copier, et la norme dit qu'il faut que tous
les éléments dans une collection standard soient copiables.
À peu près tout ce que on peut faire avec un pointeur invalide, c'est de lui affecter une nouvelle valeur. Même lire simplement le pointeur est un comportement indéfini. En termes de la norme, on ne peut pas le copier, et la norme dit qu'il faut que tous les éléments dans une collection standard soient copiables.
Merci pour cette clarification.
xavier
Fabien LE LEZ
On Tue, 18 Jan 2005 12:21:51 +0100, xavier :
La manipulation de pointeur invalide est-elle un comportement indéfini, tout simplement
Oui. Il y a trois types de pointeurs : - pointeur qui pointe sur quelque chose : valide et déréférençable, tout va bien ; - pointeur NULL ou qui pointe sur un élément "past-the-end" (en gros, l'élément juste après la fin d'un tableau) : on peut faire ce qu'on veut avec, sauf le déréférencer ; - pointeur invalide (tous les autres cas), le simple fait d'y penser peut t'attirer les foudres divines et un comportement indéfini.
Si j'ai bien tout suivi, la norme ne s'oppose pas à ce que le code suivant commande un café avec deux sucres et une pincée de sel :
int *ptr; ptr;
-- ;-)
On Tue, 18 Jan 2005 12:21:51 +0100, xavier <xtrochu@yahoo.com>:
La manipulation de pointeur invalide est-elle un
comportement indéfini, tout simplement
Oui.
Il y a trois types de pointeurs :
- pointeur qui pointe sur quelque chose : valide et
déréférençable, tout va bien ;
- pointeur NULL ou qui pointe sur un élément "past-the-end" (en
gros, l'élément juste après la fin d'un tableau) : on peut faire ce
qu'on veut avec, sauf le déréférencer ;
- pointeur invalide (tous les autres cas), le simple fait d'y
penser peut t'attirer les foudres divines et un comportement indéfini.
Si j'ai bien tout suivi, la norme ne s'oppose pas à ce que le code
suivant commande un café avec deux sucres et une pincée de sel :
La manipulation de pointeur invalide est-elle un comportement indéfini, tout simplement
Oui. Il y a trois types de pointeurs : - pointeur qui pointe sur quelque chose : valide et déréférençable, tout va bien ; - pointeur NULL ou qui pointe sur un élément "past-the-end" (en gros, l'élément juste après la fin d'un tableau) : on peut faire ce qu'on veut avec, sauf le déréférencer ; - pointeur invalide (tous les autres cas), le simple fait d'y penser peut t'attirer les foudres divines et un comportement indéfini.
Si j'ai bien tout suivi, la norme ne s'oppose pas à ce que le code suivant commande un café avec deux sucres et une pincée de sel :
int *ptr; ptr;
-- ;-)
kanze
Fabien LE LEZ wrote:
On Tue, 18 Jan 2005 12:21:51 +0100, xavier :
La manipulation de pointeur invalide est-elle un comportement indéfini, tout simplement
Oui. Il y a trois types de pointeurs : - pointeur qui pointe sur quelque chose : valide et déréférençable, tout va bien ; - pointeur NULL ou qui pointe sur un élément "past-the-end" (en gros, l'élément juste après la fin d'un tableau) : on peut faire ce qu'on veut avec, sauf le déréférencer ; - pointeur invalide (tous les autres cas), le simple fait d'y penser peut t'attirer les foudres divines et un comportement indéfini.
C'est un peu plus compliqué que ça, parce qu'il y a aussi des règles en ce qui concerne ce qu'on peut comparer pour l'inégalité, et ce qu'on ne peut pas comparer, et des règles concernant ce qui est garantie ou non dans les comparaisons d'égalité. Donc, par exemple, un pointeur « un au delà de la fin » peut comparer égal à un pointeur à un objet existant, ce qui n'est pas vrai pour un pointeur nul.
Mais c'est surtout ta catégorie deux qui est affectée. Tu ne peux pas comparer un pointeur dans la catégorie 3 ; évidemment, puisque tu n'as pas le droit de le lire.
Si j'ai bien tout suivi, la norme ne s'oppose pas à ce que le code suivant commande un café avec deux sucres et une pincée de sel :
int *ptr; ptr;
Tout à fait. Il y a même eu des implémentations où quelque chose comme :
| int * ptr ; | if ( ptr == NULL ) ...
provoquait l'équivalent d'un core dump.
Dans le cas des pointeurs dans les collections, il y a une complication en plus du fait qu'on ne sait pas quand la collection risque de lire un pointeur. En fait, la norme dit que si la collection contient jamais un élément qu'on ne peut pas lire, c'est un comportement indéfini. Mais franchement, je considère la risque dans quelque chose du genre :
| std::vector< T* > v ; | // ... | delete v[ i ] ; | v[ i ] = NULL ;
acceptable. L'expression v[ i ] doit renvoyer une référence à l'élément ; on voit mal qu'elle le lit aussi. Mais la garantie provient du bon sens et le fait que les implémentations ne font pas des choses pour rien, et non de la norme.
-- 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
Fabien LE LEZ wrote:
On Tue, 18 Jan 2005 12:21:51 +0100, xavier <xtrochu@yahoo.com>:
La manipulation de pointeur invalide est-elle un comportement
indéfini, tout simplement
Oui.
Il y a trois types de pointeurs :
- pointeur qui pointe sur quelque chose : valide et
déréférençable, tout va bien ;
- pointeur NULL ou qui pointe sur un élément "past-the-end"
(en gros, l'élément juste après la fin d'un tableau) : on peut
faire ce qu'on veut avec, sauf le déréférencer ;
- pointeur invalide (tous les autres cas), le simple fait
d'y penser peut t'attirer les foudres divines et un
comportement indéfini.
C'est un peu plus compliqué que ça, parce qu'il y a aussi des
règles en ce qui concerne ce qu'on peut comparer pour
l'inégalité, et ce qu'on ne peut pas comparer, et des règles
concernant ce qui est garantie ou non dans les comparaisons
d'égalité. Donc, par exemple, un pointeur « un au delà de la
fin » peut comparer égal à un pointeur à un objet existant, ce
qui n'est pas vrai pour un pointeur nul.
Mais c'est surtout ta catégorie deux qui est affectée. Tu ne
peux pas comparer un pointeur dans la catégorie 3 ; évidemment,
puisque tu n'as pas le droit de le lire.
Si j'ai bien tout suivi, la norme ne s'oppose pas à ce que le code
suivant commande un café avec deux sucres et une pincée de sel :
int *ptr; ptr;
Tout à fait. Il y a même eu des implémentations où quelque chose
comme :
| int * ptr ;
| if ( ptr == NULL ) ...
provoquait l'équivalent d'un core dump.
Dans le cas des pointeurs dans les collections, il y a une
complication en plus du fait qu'on ne sait pas quand la
collection risque de lire un pointeur. En fait, la norme dit que
si la collection contient jamais un élément qu'on ne peut pas
lire, c'est un comportement indéfini. Mais franchement, je
considère la risque dans quelque chose du genre :
| std::vector< T* > v ;
| // ...
| delete v[ i ] ;
| v[ i ] = NULL ;
acceptable. L'expression v[ i ] doit renvoyer une référence à
l'élément ; on voit mal qu'elle le lit aussi. Mais la garantie
provient du bon sens et le fait que les implémentations ne font
pas des choses pour rien, et non de la norme.
--
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
La manipulation de pointeur invalide est-elle un comportement indéfini, tout simplement
Oui. Il y a trois types de pointeurs : - pointeur qui pointe sur quelque chose : valide et déréférençable, tout va bien ; - pointeur NULL ou qui pointe sur un élément "past-the-end" (en gros, l'élément juste après la fin d'un tableau) : on peut faire ce qu'on veut avec, sauf le déréférencer ; - pointeur invalide (tous les autres cas), le simple fait d'y penser peut t'attirer les foudres divines et un comportement indéfini.
C'est un peu plus compliqué que ça, parce qu'il y a aussi des règles en ce qui concerne ce qu'on peut comparer pour l'inégalité, et ce qu'on ne peut pas comparer, et des règles concernant ce qui est garantie ou non dans les comparaisons d'égalité. Donc, par exemple, un pointeur « un au delà de la fin » peut comparer égal à un pointeur à un objet existant, ce qui n'est pas vrai pour un pointeur nul.
Mais c'est surtout ta catégorie deux qui est affectée. Tu ne peux pas comparer un pointeur dans la catégorie 3 ; évidemment, puisque tu n'as pas le droit de le lire.
Si j'ai bien tout suivi, la norme ne s'oppose pas à ce que le code suivant commande un café avec deux sucres et une pincée de sel :
int *ptr; ptr;
Tout à fait. Il y a même eu des implémentations où quelque chose comme :
| int * ptr ; | if ( ptr == NULL ) ...
provoquait l'équivalent d'un core dump.
Dans le cas des pointeurs dans les collections, il y a une complication en plus du fait qu'on ne sait pas quand la collection risque de lire un pointeur. En fait, la norme dit que si la collection contient jamais un élément qu'on ne peut pas lire, c'est un comportement indéfini. Mais franchement, je considère la risque dans quelque chose du genre :
| std::vector< T* > v ; | // ... | delete v[ i ] ; | v[ i ] = NULL ;
acceptable. L'expression v[ i ] doit renvoyer une référence à l'élément ; on voit mal qu'elle le lit aussi. Mais la garantie provient du bon sens et le fait que les implémentations ne font pas des choses pour rien, et non de la norme.
-- 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
drkm
writes:
Tout à fait. Il y a même eu des implémentations où quelque chose comme :
| int * ptr ; | if ( ptr == NULL ) ...
provoquait l'équivalent d'un core dump.
À quoi était-ce du ?
--drkm
kanze@gabi-soft.fr writes:
Tout à fait. Il y a même eu des implémentations où quelque chose
comme :
Tout à fait. Il y a même eu des implémentations où quelque chose comme :
| int * ptr ; | if ( ptr == NULL ) ...
provoquait l'équivalent d'un core dump.
À quoi était-ce du ?
--drkm
Gabriel Dos Reis
drkm writes:
| writes: | | > Tout à fait. Il y a même eu des implémentations où quelque chose | > comme : | | > | int * ptr ; | > | if ( ptr == NULL ) ... | | > provoquait l'équivalent d'un core dump. | | À quoi était-ce du ?
lecture d'une variable non-initialisée[*] => fonctionnement indéfini.
[*] excepté char et variantes
-- Gaby
drkm <usenet.fclcxx@fgeorges.org> writes:
| kanze@gabi-soft.fr writes:
|
| > Tout à fait. Il y a même eu des implémentations où quelque chose
| > comme :
|
| > | int * ptr ;
| > | if ( ptr == NULL ) ...
|
| > provoquait l'équivalent d'un core dump.
|
| À quoi était-ce du ?
lecture d'une variable non-initialisée[*] => fonctionnement indéfini.
| writes: | | > Tout à fait. Il y a même eu des implémentations où quelque chose | > comme : | | > | int * ptr ; | > | if ( ptr == NULL ) ... | | > provoquait l'équivalent d'un core dump. | | À quoi était-ce du ?
lecture d'une variable non-initialisée[*] => fonctionnement indéfini.
[*] excepté char et variantes
-- Gaby
Jean-Marc Bourguet
drkm writes:
writes:
Tout à fait. Il y a même eu des implémentations où quelque chose comme :
| int * ptr ; | if ( ptr == NULL ) ...
provoquait l'équivalent d'un core dump.
À quoi était-ce du ?
Une possibilite: si j'ai bonne memoire, le chargement d'un descripteur de segment invalide dans un registre de segment dans les 80286 et au-dela genere une interruption.
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
drkm <usenet.fclcxx@fgeorges.org> writes:
kanze@gabi-soft.fr writes:
Tout à fait. Il y a même eu des implémentations où quelque chose
comme :
| int * ptr ;
| if ( ptr == NULL ) ...
provoquait l'équivalent d'un core dump.
À quoi était-ce du ?
Une possibilite: si j'ai bonne memoire, le chargement d'un descripteur
de segment invalide dans un registre de segment dans les 80286 et
au-dela genere une interruption.
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
Tout à fait. Il y a même eu des implémentations où quelque chose comme :
| int * ptr ; | if ( ptr == NULL ) ...
provoquait l'équivalent d'un core dump.
À quoi était-ce du ?
Une possibilite: si j'ai bonne memoire, le chargement d'un descripteur de segment invalide dans un registre de segment dans les 80286 et au-dela genere une interruption.
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
kanze
Jean-Marc Bourguet wrote:
drkm writes:
writes:
Tout à fait. Il y a même eu des implémentations où quelque chose comme :
| int * ptr ; | if ( ptr == NULL ) ...
provoquait l'équivalent d'un core dump.
À quoi était-ce du ?
Une possibilite: si j'ai bonne memoire, le chargement d'un descripteur de segment invalide dans un registre de segment dans les 80286 et au-dela genere une interruption.
En effet. La façon la plus simple de charger une adresse avec segment, c'étaiest les instructions les, lfs ou lgs. La plus simple, mais pas la plus rapide, et je crois que des meilleurs compilateurs utilisaient deux mov à la place. À moins qu'ils comptaient déréférencer par la suite, par exemple dans quelque chose comme :
int i = (ptr == NULL ? 0 : *ptr) ;
-- 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
Jean-Marc Bourguet wrote:
drkm <usenet.fclcxx@fgeorges.org> writes:
kanze@gabi-soft.fr writes:
Tout à fait. Il y a même eu des implémentations où quelque
chose comme :
| int * ptr ;
| if ( ptr == NULL ) ...
provoquait l'équivalent d'un core dump.
À quoi était-ce du ?
Une possibilite: si j'ai bonne memoire, le chargement d'un
descripteur de segment invalide dans un registre de segment
dans les 80286 et au-dela genere une interruption.
En effet. La façon la plus simple de charger une adresse avec
segment, c'étaiest les instructions les, lfs ou lgs. La plus
simple, mais pas la plus rapide, et je crois que des meilleurs
compilateurs utilisaient deux mov à la place. À moins qu'ils
comptaient déréférencer par la suite, par exemple dans quelque
chose comme :
int i = (ptr == NULL ? 0 : *ptr) ;
--
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
Tout à fait. Il y a même eu des implémentations où quelque chose comme :
| int * ptr ; | if ( ptr == NULL ) ...
provoquait l'équivalent d'un core dump.
À quoi était-ce du ?
Une possibilite: si j'ai bonne memoire, le chargement d'un descripteur de segment invalide dans un registre de segment dans les 80286 et au-dela genere une interruption.
En effet. La façon la plus simple de charger une adresse avec segment, c'étaiest les instructions les, lfs ou lgs. La plus simple, mais pas la plus rapide, et je crois que des meilleurs compilateurs utilisaient deux mov à la place. À moins qu'ils comptaient déréférencer par la suite, par exemple dans quelque chose comme :
int i = (ptr == NULL ? 0 : *ptr) ;
-- 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