"Henri de Solages" a écrit dans le message de news: dfp0sk$4a1$
Si tu as un tableau, pourquoi voudrais-tu le terminer par par NULL ? Connaître la taille du tableau ne suffit pas pour savoir quand s'arrêter ?
C'est bien ce que je pensais faire pour le cas avéré où l'on n'a pas le droit d'utiliser NULL, mais c'est plus lourd : quand je passe le tableau à une fonction, il faut aussi lui passer sa taille.
Pas si c'est un conteneur : vector::size( ), etc.
-- -Stan
"Henri de Solages" <solages@CICT.fr_> a écrit dans le message de news:
dfp0sk$4a1$1@news.cict.fr...
Si tu as un tableau, pourquoi voudrais-tu le terminer par par NULL ?
Connaître la taille du tableau ne suffit pas pour savoir quand
s'arrêter ?
C'est bien ce que je pensais faire pour le cas avéré où l'on n'a pas le
droit d'utiliser NULL,
mais c'est plus lourd : quand je passe le tableau à une fonction, il faut
aussi lui passer sa taille.
"Henri de Solages" a écrit dans le message de news: dfp0sk$4a1$
Si tu as un tableau, pourquoi voudrais-tu le terminer par par NULL ? Connaître la taille du tableau ne suffit pas pour savoir quand s'arrêter ?
C'est bien ce que je pensais faire pour le cas avéré où l'on n'a pas le droit d'utiliser NULL, mais c'est plus lourd : quand je passe le tableau à une fonction, il faut aussi lui passer sa taille.
Pas si c'est un conteneur : vector::size( ), etc.
-- -Stan
Loïc Joly
Pourquoi ne pas placer ces itérateurs dans un vector ?
Je n'aime pas les vector car, quand on fait un erase, les iterateurs sur les élements suivants ne sont plus valides. J'aime bien qu'on fasse suivre le courrier quand on déménage.
En ce cas là, pourquoi ne pas placer ces itérateurs dans une list ?
-- Loïc
Pourquoi ne pas placer ces itérateurs dans un vector ?
Je n'aime pas les vector car, quand on fait un erase, les iterateurs sur
les élements suivants ne sont plus valides. J'aime bien qu'on fasse
suivre le courrier quand on déménage.
En ce cas là, pourquoi ne pas placer ces itérateurs dans une list ?
Pourquoi ne pas placer ces itérateurs dans un vector ?
Je n'aime pas les vector car, quand on fait un erase, les iterateurs sur les élements suivants ne sont plus valides. J'aime bien qu'on fasse suivre le courrier quand on déménage.
En ce cas là, pourquoi ne pas placer ces itérateurs dans une list ?
-- Loïc
Gabriel Dos Reis
Henri de Solages writes:
| > Si tu as un tableau, pourquoi voudrais-tu le terminer par par NULL ? | > Connaître la taille du tableau ne suffit pas pour savoir quand | > s'arrêter ? | | C'est bien ce que je pensais faire pour le cas avéré où l'on n'a pas le droit d'utiliser NULL, | mais c'est plus lourd : quand je passe le tableau à une fonction, il | faut aussi lui passer sa taille.
Non. Tu passes le vecteur (par reference ou const reference) et il connait sa taille.
-- Gaby
Henri de Solages <solages@CICT.fr_> writes:
| > Si tu as un tableau, pourquoi voudrais-tu le terminer par par NULL ?
| > Connaître la taille du tableau ne suffit pas pour savoir quand
| > s'arrêter ?
|
| C'est bien ce que je pensais faire pour le cas avéré où l'on n'a pas le droit d'utiliser NULL,
| mais c'est plus lourd : quand je passe le tableau à une fonction, il
| faut aussi lui passer sa taille.
Non. Tu passes le vecteur (par reference ou const reference) et il
connait sa taille.
| > Si tu as un tableau, pourquoi voudrais-tu le terminer par par NULL ? | > Connaître la taille du tableau ne suffit pas pour savoir quand | > s'arrêter ? | | C'est bien ce que je pensais faire pour le cas avéré où l'on n'a pas le droit d'utiliser NULL, | mais c'est plus lourd : quand je passe le tableau à une fonction, il | faut aussi lui passer sa taille.
Non. Tu passes le vecteur (par reference ou const reference) et il connait sa taille.
-- Gaby
Gabriel Dos Reis
Henri de Solages writes:
| >> Je remarque cependant que ni c++ ni icpc (compilateur d'Intel) | >> ne me jettent quand j'affecte NULL à un itérateur. | > Amusant: tu as un bout de code. | | # include <iostream> | # include <string> | # include <list> | | using namespace std ; | | int main( int argc, char ** argv ) { | list< string >::const_iterator i_nombres = NULL ; | | if( i_nombres != NULL ) | cerr << "i_nombresn" ; | else | cerr << "non i_nombresn" ; | return 0 ; | }
à l'évidence, c'est un bug dans GCC/libstdc++. Si je modifie ton program comme suit (en ajoutant un vector)
# include <iostream> # include <string> # include <list> #include <vector>
using namespace std ;
int main( int argc, char ** argv ) { list< string >::const_iterator i_nombres = NULL ; vector<string>::const_iterator p = NULL;
hs.C: In function 'int main(int, char**)': hs.C:10: error: conversion from 'int' to non-scalar type '__gnu_cxx::__normal_iterator<const std::string*, std::vector<std::string, std::allocator<std::string> > >' requested
-- Gaby
Henri de Solages <solages@CICT.fr_> writes:
| >> Je remarque cependant que ni c++ ni icpc (compilateur d'Intel)
| >> ne me jettent quand j'affecte NULL à un itérateur.
| > Amusant: tu as un bout de code.
|
| # include <iostream>
| # include <string>
| # include <list>
|
| using namespace std ;
|
| int main( int argc, char ** argv ) {
| list< string >::const_iterator i_nombres = NULL ;
|
| if( i_nombres != NULL )
| cerr << "i_nombresn" ;
| else
| cerr << "non i_nombresn" ;
| return 0 ;
| }
à l'évidence, c'est un bug dans GCC/libstdc++. Si je modifie ton program
comme suit (en ajoutant un vector)
# include <iostream>
# include <string>
# include <list>
#include <vector>
using namespace std ;
int main( int argc, char ** argv ) {
list< string >::const_iterator i_nombres = NULL ;
vector<string>::const_iterator p = NULL;
hs.C: In function 'int main(int, char**)':
hs.C:10: error: conversion from 'int' to non-scalar type '__gnu_cxx::__normal_iterator<const std::string*, std::vector<std::string, std::allocator<std::string> > >' requested
| >> Je remarque cependant que ni c++ ni icpc (compilateur d'Intel) | >> ne me jettent quand j'affecte NULL à un itérateur. | > Amusant: tu as un bout de code. | | # include <iostream> | # include <string> | # include <list> | | using namespace std ; | | int main( int argc, char ** argv ) { | list< string >::const_iterator i_nombres = NULL ; | | if( i_nombres != NULL ) | cerr << "i_nombresn" ; | else | cerr << "non i_nombresn" ; | return 0 ; | }
à l'évidence, c'est un bug dans GCC/libstdc++. Si je modifie ton program comme suit (en ajoutant un vector)
# include <iostream> # include <string> # include <list> #include <vector>
using namespace std ;
int main( int argc, char ** argv ) { list< string >::const_iterator i_nombres = NULL ; vector<string>::const_iterator p = NULL;
hs.C: In function 'int main(int, char**)': hs.C:10: error: conversion from 'int' to non-scalar type '__gnu_cxx::__normal_iterator<const std::string*, std::vector<std::string, std::allocator<std::string> > >' requested
-- Gaby
Gabriel Dos Reis
Marc Boyer writes:
| Henri de Solages a écrit : | >>> Je remarque cependant que ni c++ ni icpc (compilateur d'Intel) ne me jettent quand | >>>j'affecte NULL à un itérateur. | >> | >> Amusant: tu as un bout de code. | > | > # include <iostream> | > # include <string> | > # include <list> | > | > using namespace std ; | > | > int main( int argc, char ** argv ) { | > list< string >::const_iterator i_nombres = NULL ; | > | > if( i_nombres != NULL ) | > cerr << "i_nombresn" ; | > else | > cerr << "non i_nombresn" ; | > return 0 ; | > } | | En effet, compile sans rien dire avec mon g++ (gcc 3.3.5). | Je suis étonné.
Yup. Essaie
#inclue <vector>
int main() { std::vector<int>::const_iterator p = NULL; }
[...]
| - pour les experts, est-ce qu'il ne faut pas considérer | l'absence d'explicit comme un bug à rapporter à | l'équipe de GCC ?
C'en est un. Peux-tu faire un bug report ? (mets moi en CC: du PR, mon email chez GNU est gdr at gcc dot gnu dot org).
-- Gaby
Marc Boyer <Marc.Boyer@enseeiht.yahoo.fr.invalid> writes:
| Henri de Solages <solages@CICT.fr_> a écrit :
| >>> Je remarque cependant que ni c++ ni icpc (compilateur d'Intel) ne me jettent quand
| >>>j'affecte NULL à un itérateur.
| >>
| >> Amusant: tu as un bout de code.
| >
| > # include <iostream>
| > # include <string>
| > # include <list>
| >
| > using namespace std ;
| >
| > int main( int argc, char ** argv ) {
| > list< string >::const_iterator i_nombres = NULL ;
| >
| > if( i_nombres != NULL )
| > cerr << "i_nombresn" ;
| > else
| > cerr << "non i_nombresn" ;
| > return 0 ;
| > }
|
| En effet, compile sans rien dire avec mon g++ (gcc 3.3.5).
| Je suis étonné.
Yup. Essaie
#inclue <vector>
int main()
{
std::vector<int>::const_iterator p = NULL;
}
[...]
| - pour les experts, est-ce qu'il ne faut pas considérer
| l'absence d'explicit comme un bug à rapporter à
| l'équipe de GCC ?
C'en est un. Peux-tu faire un bug report ? (mets moi en CC: du PR, mon
email chez GNU est gdr at gcc dot gnu dot org).
| Henri de Solages a écrit : | >>> Je remarque cependant que ni c++ ni icpc (compilateur d'Intel) ne me jettent quand | >>>j'affecte NULL à un itérateur. | >> | >> Amusant: tu as un bout de code. | > | > # include <iostream> | > # include <string> | > # include <list> | > | > using namespace std ; | > | > int main( int argc, char ** argv ) { | > list< string >::const_iterator i_nombres = NULL ; | > | > if( i_nombres != NULL ) | > cerr << "i_nombresn" ; | > else | > cerr << "non i_nombresn" ; | > return 0 ; | > } | | En effet, compile sans rien dire avec mon g++ (gcc 3.3.5). | Je suis étonné.
Yup. Essaie
#inclue <vector>
int main() { std::vector<int>::const_iterator p = NULL; }
[...]
| - pour les experts, est-ce qu'il ne faut pas considérer | l'absence d'explicit comme un bug à rapporter à | l'équipe de GCC ?
C'en est un. Peux-tu faire un bug report ? (mets moi en CC: du PR, mon email chez GNU est gdr at gcc dot gnu dot org).
-- Gaby
Gabriel Dos Reis
Henri de Solages writes:
| >>Je veux un tableau d'itérateurs sur des éléments d'une list. | | > Sinon, ce dont tu as besoin, c'est d'un délimiteur de | > fin, donc le end() de la liste me semble une bonne | > valeur interdite. | | Mais si j'ajoute ensuite des éléments à ma liste, le end() de la list | est-il tenu par la norme de garder une même valeur ?
Tu n'as pas à te soucier de end() -- il suffit que tu ne le stockes nulle part (c'est une proprieté intrinsèque de chaque liste à chaque instant). Stockes uniquement les itérateurs vers les éléments que tu as effectivement mis dans la liste, non des artéfacts comme begin()/end().
-- Gaby
Henri de Solages <solages@CICT.fr_> writes:
| >>Je veux un tableau d'itérateurs sur des éléments d'une list.
|
| > Sinon, ce dont tu as besoin, c'est d'un délimiteur de
| > fin, donc le end() de la liste me semble une bonne
| > valeur interdite.
|
| Mais si j'ajoute ensuite des éléments à ma liste, le end() de la list
| est-il tenu par la norme de garder une même valeur ?
Tu n'as pas à te soucier de end() -- il suffit que tu ne le stockes
nulle part (c'est une proprieté intrinsèque de chaque liste à chaque
instant). Stockes uniquement les itérateurs vers les éléments que tu
as effectivement mis dans la liste, non des artéfacts comme begin()/end().
| >>Je veux un tableau d'itérateurs sur des éléments d'une list. | | > Sinon, ce dont tu as besoin, c'est d'un délimiteur de | > fin, donc le end() de la liste me semble une bonne | > valeur interdite. | | Mais si j'ajoute ensuite des éléments à ma liste, le end() de la list | est-il tenu par la norme de garder une même valeur ?
Tu n'as pas à te soucier de end() -- il suffit que tu ne le stockes nulle part (c'est une proprieté intrinsèque de chaque liste à chaque instant). Stockes uniquement les itérateurs vers les éléments que tu as effectivement mis dans la liste, non des artéfacts comme begin()/end().
-- Gaby
Gabriel Dos Reis
Henri de Solages writes:
| | > Pourquoi ne pas placer ces itérateurs dans un vector ? | | Je n'aime pas les vector car, quand on fait un erase, les iterateurs | sur les élements suivants ne sont plus valides.
Oui mais d'après ce que tu as dit jusqu'à présent, tu ne gardes pas des itérateurs (de vecteurs) vers les itérateurs de (listes), donc ta crainte n'a aucun fondement dans ce cas ici. De plus, si tu ne fais pas de erase() sur ton tableau, pourquoi veux-tu en faire sur un vector ?
-- Gaby
Henri de Solages <solages@CICT.fr_> writes:
|
| > Pourquoi ne pas placer ces itérateurs dans un vector ?
|
| Je n'aime pas les vector car, quand on fait un erase, les iterateurs
| sur les élements suivants ne sont plus valides.
Oui mais d'après ce que tu as dit jusqu'à présent, tu ne gardes pas
des itérateurs (de vecteurs) vers les itérateurs de (listes), donc ta
crainte n'a aucun fondement dans ce cas ici. De plus, si tu ne fais
pas de erase() sur ton tableau, pourquoi veux-tu en faire sur un
vector ?
| | > Pourquoi ne pas placer ces itérateurs dans un vector ? | | Je n'aime pas les vector car, quand on fait un erase, les iterateurs | sur les élements suivants ne sont plus valides.
Oui mais d'après ce que tu as dit jusqu'à présent, tu ne gardes pas des itérateurs (de vecteurs) vers les itérateurs de (listes), donc ta crainte n'a aucun fondement dans ce cas ici. De plus, si tu ne fais pas de erase() sur ton tableau, pourquoi veux-tu en faire sur un vector ?
-- Gaby
Gabriel Dos Reis
"kanze" writes:
| ci-dessus. J'ai l'impression que la seule différence entre leur | code et ce que je faisais auparavent (depuis au moins vingt ans | maintenant), c'est qu'ils allouent la racine dynamiquement, | tandis que chez moi, elle était membre.
template<typename _Tp, typename _Alloc = std::allocator<_Tp> > class list : protected _List_base<_Tp, _Alloc> { [...]
-- Gaby
"kanze" <kanze@gabi-soft.fr> writes:
| ci-dessus. J'ai l'impression que la seule différence entre leur
| code et ce que je faisais auparavent (depuis au moins vingt ans
| maintenant), c'est qu'ils allouent la racine dynamiquement,
| tandis que chez moi, elle était membre.
| ci-dessus. J'ai l'impression que la seule différence entre leur | code et ce que je faisais auparavent (depuis au moins vingt ans | maintenant), c'est qu'ils allouent la racine dynamiquement, | tandis que chez moi, elle était membre.
template<typename _Tp, typename _Alloc = std::allocator<_Tp> > class list : protected _List_base<_Tp, _Alloc> { [...]
-- Gaby
Gabriel Dos Reis
Marc Boyer writes:
[...]
| > Je crois. Je crois qu'il font à peu près comme j'ai fait | > ci-dessus. J'ai l'impression que la seule différence entre leur | > code et ce que je faisais auparavent (depuis au moins vingt ans | > maintenant), c'est qu'ils allouent la racine dynamiquement, | | Oui.
Non, il n'y a pas d'allocation dynamique de la racine.
| La classe possède un champ _M_node, qui semble être
| cette racine (d'ailleurs, end() se contente de retourner | _M_node et begin() retourne _M_node->next), et le constructeur | fait | _M_node= _M_get_node();
Marc Boyer <Marc.Boyer@enseeiht.yahoo.fr.invalid> writes:
[...]
| > Je crois. Je crois qu'il font à peu près comme j'ai fait
| > ci-dessus. J'ai l'impression que la seule différence entre leur
| > code et ce que je faisais auparavent (depuis au moins vingt ans
| > maintenant), c'est qu'ils allouent la racine dynamiquement,
|
| Oui.
Non, il n'y a pas d'allocation dynamique de la racine.
| La classe possède un champ _M_node, qui semble être
| cette racine (d'ailleurs, end() se contente de retourner
| _M_node et begin() retourne _M_node->next), et le constructeur
| fait
| _M_node= _M_get_node();
| > Je crois. Je crois qu'il font à peu près comme j'ai fait | > ci-dessus. J'ai l'impression que la seule différence entre leur | > code et ce que je faisais auparavent (depuis au moins vingt ans | > maintenant), c'est qu'ils allouent la racine dynamiquement, | | Oui.
Non, il n'y a pas d'allocation dynamique de la racine.
| La classe possède un champ _M_node, qui semble être
| cette racine (d'ailleurs, end() se contente de retourner | _M_node et begin() retourne _M_node->next), et le constructeur | fait | _M_node= _M_get_node();
| Gabriel Dos Reis wrote: | > Loïc Joly writes: | > | > Bonjour. | > | > Est-il légal d'assigner la valeur NULL à un itérateur ? | > | | Souvent, l'équivalent moral de NULL pour un itérateur sur une | > | collection "c" est c.end() | > Cela peut cependant réserver des surprises. | > list<int> l; | > // ... | > copy(l.begin(), l.end(), back_inserter(l)); | | JE vois pas le piege la. Tu peux expliquer stp?
int main() { using namespace std; list<int> l; l.push_back(9); copy(l.begin(), l.end(), back_inserter(l)); }
boucle indéfiniment, parce que même si l.end() est évalué avant de rentrer dans le coprs de copy(), sa valeur intrinsèque change à chaque push_back() -- ce n'est jamais la même, en particulier, elle marque la fin de la « nouvelle » liste qui ne peut jamais être atteinte dans la boucle de copy().
-- Gaby
korchkidu <korch_ki_du@yahoo.fr> writes:
| Gabriel Dos Reis wrote:
| > Loïc Joly <loic.actarus.joly@wanadoo.fr> writes:
| > | > Bonjour.
| > | > Est-il légal d'assigner la valeur NULL à un itérateur ?
| > | | Souvent, l'équivalent moral de NULL pour un itérateur sur une
| > | collection "c" est c.end()
| > Cela peut cependant réserver des surprises.
| > list<int> l;
| > // ...
| > copy(l.begin(), l.end(), back_inserter(l));
|
| JE vois pas le piege la. Tu peux expliquer stp?
int main()
{
using namespace std;
list<int> l;
l.push_back(9);
copy(l.begin(), l.end(), back_inserter(l));
}
boucle indéfiniment, parce que même si l.end() est évalué avant de
rentrer dans le coprs de copy(), sa valeur intrinsèque change à chaque
push_back() -- ce n'est jamais la même, en particulier, elle marque la
fin de la « nouvelle » liste qui ne peut jamais être atteinte dans la
boucle de copy().
| Gabriel Dos Reis wrote: | > Loïc Joly writes: | > | > Bonjour. | > | > Est-il légal d'assigner la valeur NULL à un itérateur ? | > | | Souvent, l'équivalent moral de NULL pour un itérateur sur une | > | collection "c" est c.end() | > Cela peut cependant réserver des surprises. | > list<int> l; | > // ... | > copy(l.begin(), l.end(), back_inserter(l)); | | JE vois pas le piege la. Tu peux expliquer stp?
int main() { using namespace std; list<int> l; l.push_back(9); copy(l.begin(), l.end(), back_inserter(l)); }
boucle indéfiniment, parce que même si l.end() est évalué avant de rentrer dans le coprs de copy(), sa valeur intrinsèque change à chaque push_back() -- ce n'est jamais la même, en particulier, elle marque la fin de la « nouvelle » liste qui ne peut jamais être atteinte dans la boucle de copy().