 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
hyronn@gmail.com Guest
|
Posted: Sat Mar 17, 2007 11:44 pm Post subject: Séquence des élèments d'un vector |
|
|
Bonsoir,
Est-on assuré que les éléments d'un std::vector se suivent en mémoire?
Je veux utiliser un vector pour me décharger de l'allocation dynamique
t'un tableau temporaire de caractères.
#include <cstdio>
#include <vector>
void parse1(const char* const txt_buffer)
{
vector<char> str;
str.reserve(FILENAME_MAX);
sscanf(txt_buffer, " %*s \" %s ", (char*) &str[0] );
}
Ca marche sous VC++ 2003.
Mais est-ce standard et/ou portable?
J'ai aussi essayé ceci, mais ça ne marche pas dans tous les cas et
éclanche parfois des exceptions. Je soupsonne l'implémentation de ne
pas vraiment effectuer le reserve().
void parse2(const char* const txt_buffer)
{
string s;
s.reserve(FILENAME_MAX);
sscanf(txt_buffer, " %*s \" %s ", const_cast<char*>(s.data()) );
}
Rq: je ne peux pas me permettre d'utiliser les iostreams pour des
raisons de performance. La fonction parser doit interpréter des
fichiers de plusieurs centaines de ko de texte.
Merci |
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Sun Mar 18, 2007 12:22 am Post subject: Re: Séquence des élèments d'un vector |
|
|
On 17 Mar 2007 11:44:23 -0700, "hyronn (AT) gmail (DOT) com" <hyronn (AT) gmail (DOT) com>:
| Quote: | Est-on assuré que les éléments d'un std::vector se suivent en mémoire?
|
Oui.
Depuis assez récemment, c'est garanti par la norme.
Avant, c'était à peu près garanti aussi, car il était impossible
d'implémenter std::vector<> autrement.
| Quote: | J'ai aussi essayé ceci, mais ça ne marche pas dans tous les cas
[...] const_cast [...]
|
Faut pas chercher plus loin la source du problème...
Et je confirme que dans ton cas, c'est std::vector<char> qu'il faut
utiliser. |
|
| Back to top |
|
 |
Loïc Joly Guest
|
Posted: Sun Mar 18, 2007 1:39 am Post subject: Re: Séquence des élèments d'un ve ctor |
|
|
hyronn (AT) gmail (DOT) com a écrit :
| Quote: | void parse1(const char* const txt_buffer)
{
vector<char> str;
str.reserve(FILENAME_MAX);
sscanf(txt_buffer, " %*s \" %s ", (char*) &str[0] );
}
Ca marche sous VC++ 2003.
|
J'en suis bien surpris... Après ce code, str.size() vaut encore 0. Il
faut remplacer le reserve par resize. Avec le problème que dans ce cas,
on initialise forcément la zone mémoire en question, pour rien.
--
Loïc |
|
| Back to top |
|
 |
Mathias Gaunard Guest
|
Posted: Sun Mar 18, 2007 5:48 am Post subject: Re: Séquence des élèments d'un ve ctor |
|
|
hyronn (AT) gmail (DOT) com a écrit :
| Quote: | Bonsoir,
Est-on assuré que les éléments d'un std::vector se suivent en mémoire?
Je veux utiliser un vector pour me décharger de l'allocation dynamique
t'un tableau temporaire de caractères.
#include <cstdio
#include <vector
void parse1(const char* const txt_buffer)
{
vector<char> str;
str.reserve(FILENAME_MAX);
sscanf(txt_buffer, " %*s \" %s ", (char*) &str[0] );
}
|
Ce serait plutôt
void parse1(const char* txt_buffer);
{
vector<char> str(FILENAME_MAX);
sscanf(txt_buffer, " %*s \" %s ", &str[0] );
}
1) le cast est inutile. Les casts étant une chose dangereuse à éviter
(particulièrement les casts C), si en plus c'est inutile, c'est quand
même con d'en mettre.
2) std::vector ne garantit rien pour l'accès à la mémoire réservée.
Il te faut des vrais objets.
Donc n'utilise pas reserve mais resize. Ici, on peut tout simplement
utiliser le constructeur
3) FILENAME_MAX est probablement une constante fixe du préprocesseur.
Par conséquent, pourquoi ne pas utiliser un tableau normal sur la pile ?
4) Ta fonction ne fait rien d'utile avec str. |
|
| Back to top |
|
 |
Mathias Gaunard Guest
|
Posted: Sun Mar 18, 2007 5:49 am Post subject: Re: Séquence des élèments d'un ve ctor |
|
|
hyronn (AT) gmail (DOT) com a écrit :
| Quote: | void parse1(const char* const txt_buffer)
|
Ah oui, et le second const est sans intérêt, puisque les arguments sont
passés ici par valeur. |
|
| Back to top |
|
 |
hyronn@gmail.com Guest
|
Posted: Sun Mar 18, 2007 9:11 am Post subject: Re: Séquence des élèments d'un vector |
|
|
On 17 mar, 21:39, Loïc Joly <loic.actarus.j...@numericable.fr> wrote:
| Quote: | hyr...@gmail.com a écrit :
void parse1(const char* const txt_buffer)
{
vector<char> str;
str.reserve(FILENAME_MAX);
sscanf(txt_buffer, " %*s \" %s ", (char*) &str[0] );
}
Ca marche sous VC++ 2003.
J'en suis bien surpris... Après ce code, str.size() vaut encore 0. Il
faut remplacer le reserve par resize. Avec le problème que dans ce cas,
on initialise forcément la zone mémoire en question, pour rien.
|
Juste par chance en fait!
Reserve() ou le constructeur a bien alloué de la mémoire.
J'écris sur cette emplacement, sans invoquer les procédures du
vector,
il est donc normal que size() == 0.
Je suis conscient du gaspillage de mémoire. L'ordre de grandeur est de
33k, ce qui est convenable au vu de mon "cahier des charges". |
|
| Back to top |
|
 |
hyronn@gmail.com Guest
|
Posted: Sun Mar 18, 2007 9:11 am Post subject: Re: Séquence des élèments d'un vector |
|
|
| Quote: | void parse1(const char* const txt_buffer)
Ah oui, et le second const est sans intérêt, puisque les arguments sont
passés ici par valeur.
|
Je ne comprend pas.
J'indique au compilateur que txt_buffer ne sera pas modifié afin qu'il
puisse effectuer une optimisation dont je n'ai peut être pas
connaissance.
Quel est le pb?
Merci |
|
| Back to top |
|
 |
hyronn@gmail.com Guest
|
Posted: Sun Mar 18, 2007 9:11 am Post subject: Re: Séquence des élèments d'un vector |
|
|
| Quote: | 2) std::vector ne garantit rien pour l'accès à la mémoire réservée.
Il te faut des vrais objets.
Donc n'utilise pas reserve mais resize. Ici, on peut tout simplement
utiliser le constructeur
ok |
| Quote: | 3) FILENAME_MAX est probablement une constante fixe du préprocesseur.
Par conséquent, pourquoi ne pas utiliser un tableau normal sur la pile ?
Je m'attendais à ce que FILENAME_MAX (de <cstdio>) soit plus grand que |
la pile.
Un pile usuelle fait dans les 8k et MAX_PATH (constante windowsienne
similaire) fait 32k
Je craignais un stack overflow.
Mais sur mon implementation (VC++2003) FILENAME_MAX = 260
Donc la pile fera l'affaire.
Mais question portabilité, c bof..
Auriez-vous l'aimabilité de rapporter la valeur de FILENAME_MAX sur
vos implémentation Merci
| Quote: | 4) Ta fonction ne fait rien d'utile avec str.
C'était un exemple. |
|
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Sun Mar 18, 2007 3:05 pm Post subject: Re: Séquence des élèments d'un vector |
|
|
On Mar 17, 7:44 pm, "hyr...@gmail.com" <hyr...@gmail.com> wrote:
| Quote: | Est-on assuré que les éléments d'un std::vector se suivent en mémoire?
Je veux utiliser un vector pour me décharger de l'allocation dynamique
t'un tableau temporaire de caractères.
#include <cstdio
#include <vector
void parse1(const char* const txt_buffer)
{
vector<char> str;
str.reserve(FILENAME_MAX);
sscanf(txt_buffer, " %*s \" %s ", (char*) &str[0] );
}
Ca marche sous VC++ 2003.
|
Ça ne marche pas du tout. Reserve() ne change pas la taille du
vecteur. Ce qu'il te faut, c'est resize(), non réserve.
| Quote: | Mais est-ce standard et/ou portable?
|
Avec resize(), oui. Et tu n'as pas besoin du cast pour le
dernier parametre.
| Quote: | J'ai aussi essayé ceci, mais ça ne marche pas dans tous les cas et
éclanche parfois des exceptions. Je soupsonne l'implémentation de ne
pas vraiment effectuer le reserve().
void parse2(const char* const txt_buffer)
{
string s;
s.reserve(FILENAME_MAX);
sscanf(txt_buffer, " %*s \" %s ", const_cast<char*>(s.data()) );
}
|
La norme n'exige pas que reserve() fasse quoique ce soit dans le
cas de std::string. Elle n'exige pas (encore) non plus que le
pointeur renvoyé par data() correspond au contenu de la chaîne.
Dans la pratique, si tu utilises resize() à la place de
reserve(), ça doit marcher avec toutes les implémentations
existantes. Il y a une proposition devant le comité (acceptée en
principe, je crois) pour exiger la contiguïté du buffer dans
basic_string aussi, et de fournir une version non-const de
data().
| Quote: | Rq: je ne peux pas me permettre d'utiliser les iostreams pour des
raisons de performance. La fonction parser doit interpréter des
fichiers de plusieurs centaines de ko de texte.
|
Et qu'est-ce qui te dit que sscanf soit plus performant ? Ça
doit dépendre beaucoup de l'implémentation.
Si c'est vraiment une question de performance, strchr, etc. sur
la chaîne initiale est probablement ce qui serait la plus
rapide. Ensuite, la construction des chaînes dont tu as besoin
à partir des pointeurs trouvés.
--
James Kanze (Gabi Software) email: james.kanze (AT) gmail (DOT) com
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 |
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Sun Mar 18, 2007 3:13 pm Post subject: Re: Séquence des élèments d'un vector |
|
|
On Mar 18, 9:54 am, "hyr...@gmail.com" <hyr...@gmail.com> wrote:
| Quote: | void parse1(const char* const txt_buffer)
Ah oui, et le second const est sans intérêt, puisque les arguments sont
passés ici par valeur.
Je ne comprend pas.
J'indique au compilateur que txt_buffer ne sera pas modifié afin qu'il
puisse effectuer une optimisation dont je n'ai peut être pas
connaissance.
Quel est le pb?
|
Aucun problème, mais il apporte en fait assez peu, vue qu'il ne
conditionne qu'une variable locale, dont tous les accès sont
visibles, et par le compilateur, et par le lecteur.
Son utilisation est, à mon avis, une question de style. La
déclaration de la fonction (que voit les autres utilisateurs) ne
doit pas le comporter -- là, il ne signifie rien. Alors,
certains préfère que les paramètres dans la définition
s'écrivent de façon exactement identiques à ceux de la
déclaration, quitte à rénouncer à l'avantage d'une const locale.
D'autres préfère les avantages du const, même au prix que la
déclaration et la définition apparaissent légèrement
différentes.
Personnellement, je n'utilise pas le const dans ce cas-ci, mais
comme j'ai dit, c'est vraiment une question de style, et je ne
rejetterais certainement pas du code dans une revue de code pour
cette raison. Si tu te sens plus à l'aise avec le const, il n'y
a aucune raison de changer.
--
James Kanze (Gabi Software) email: james.kanze (AT) gmail (DOT) com
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 |
|
| Back to top |
|
 |
Mathias Gaunard Guest
|
Posted: Sun Mar 18, 2007 9:07 pm Post subject: Re: Séquence des élèments d'un ve ctor |
|
|
hyronn (AT) gmail (DOT) com a écrit :
| Quote: | Un pile usuelle fait dans les 8k
|
Une pile usuelle de 1980 ?
Un compilateur pourrait a priori détecter, modulo l'usage de la
récursivité, de quelle taille la pile doit être et t'avertir dans le cas
où la pile nécessaire serait trop grande.
| Quote: | et MAX_PATH (constante windowsienne
similaire) fait 32k
|
Un chemin et un nom de fichier c'est pas exactement la même chose.
| Quote: | Auriez-vous l'aimabilité de rapporter la valeur de FILENAME_MAX sur
vos implémentation
|
Le plus long nom possible que j'ai trouvé en regardant les
caractéristiques des systèmes de fichiers c'est 4032 octets.
Mais 255 est quand même une valeur récurrente. |
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Mon Mar 19, 2007 12:12 am Post subject: Re: Séquence des élèments d'un vector |
|
|
On 18 Mar 2007 01:54:45 -0700, "hyronn (AT) gmail (DOT) com" <hyronn (AT) gmail (DOT) com>:
| Quote: | void parse1(const char* const txt_buffer)
Ah oui, et le second const est sans intérêt, puisque les arguments sont
passés ici par valeur.
[...]
Quel est le pb?
|
En plus de l'argumentation de James, je trouve que mettre un "const"
avant ce à quoi il s'applique, et un autre "const" après ce à quoi il
s'applique, est un peu bancal et peu lisible.
Mébon, c'est juste une impression personnelle, qui n'engage que moi. |
|
| Back to top |
|
 |
Sylvain Togni Guest
|
Posted: Mon Mar 19, 2007 9:18 pm Post subject: Re: Séquence des élèments d'un ve ctor |
|
|
hyronn (AT) gmail (DOT) com wrote:
| Quote: | Par exemple:
on fixe une valeur et par la suite on a besoin de sa racine:
const float pi = 7;
float f = sqrt(pi).
Si un compilateur soit disant évolué appelle sqrt à chaque itération,
il est pas très malin puisque pi et sqrt sont connues au moment de la
compilation*. Je m'attend à ce que ces 2 lignes, écrites ainsi pour
assurer la lisibilité du code, soient remplacée par l'équivalent en
langage machine de
float f = 1.772004515;
|
Oui, peut-être que le compilateur fera l'optimisation, mais
il la fera aussi bien si la variable pi n'est pas déclarée
const.
Les compilateurs, dans la plupart des cas, savent mieux que
le programmeur quelle variable est constante et quelle ne
l'est pas. Preuve en est, ils émettent une erreur quand
on essaie de modifier une variable const.
--
Sylvain Togni |
|
| Back to top |
|
 |
Sylvain Togni Guest
|
Posted: Mon Mar 19, 2007 9:22 pm Post subject: Re: Séquence des élèments d'un ve ctor |
|
|
Michel Decima wrote:
| Quote: | Petite précision : le mot-clé const n'a aucune incidence
sur les performances, il sert juste à éviter certains bugs
et à améliorer la lisibilité du code.
La documentation de mon compilateur (xlC-6/AIX) me dit "Use the const
qualifier whenever possible" dans la section "Coding Techniques That Can
Improve Performance".
D'un autre coté, le titre de la section dit que ca _peut_ améliorer les
choses, pas que ca le fait systématiquement.
|
Je ne sais pas, la seule différence que je vois c'est qu'en
utilisant const on est assez souvent amené à définir deux fois
certaines fonctions comme les getteurs, une version const et
une version non-const, ce qui augmente la taille du code et
diminue un peu la vitesse pour des raisons de localité.
--
Sylvain Togni |
|
| Back to top |
|
 |
Michel Decima Guest
|
Posted: Mon Mar 19, 2007 9:39 pm Post subject: Re: Séquence des élèments d'un ve ctor |
|
|
Sylvain Togni a écrit :
| Quote: | Michel Decima wrote:
La documentation de mon compilateur (xlC-6/AIX) me dit "Use the const
qualifier whenever possible" dans la section "Coding Techniques That
Can Improve Performance".
D'un autre coté, le titre de la section dit que ca _peut_ améliorer
les choses, pas que ca le fait systématiquement.
Je ne sais pas, la seule différence que je vois c'est qu'en
utilisant const on est assez souvent amené à définir deux fois
certaines fonctions comme les getteurs, une version const et
une version non-const, ce qui augmente la taille du code et
diminue un peu la vitesse pour des raisons de localité.
|
Je ne sais pas non plus, je n'ai jamais fait de tests dans ce sens.
Et la doc. en question ne dit pas si'il faut utiliser const sur
des variables, des arguments de fonction ou des fonction membres pour
obtenir un effet, ni quel effet d'ailleurs.
Peut etre que l'optimiseur est un peu benêt, il ne sais pas detecter
les constantes tout seul, et il faut l'aider un peu... mais j'ai un
gros doute quand meme, faut pas sous-estimer les capacités de ce genre
d'engins. |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|