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

Séquence des élèments d'un vector

36 réponses
Avatar
hyronn
Bonsoir,

Est-on assur=E9 que les =E9l=E9ments d'un std::vector se suivent en m=E9moi=
re?
Je veux utiliser un vector pour me d=E9charger de l'allocation dynamique
t'un tableau temporaire de caract=E8res.

#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=E9 ceci, mais =E7a ne marche pas dans tous les cas et
=E9clanche parfois des exceptions. Je soupsonne l'impl=E9mentation 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=E9ter des
fichiers de plusieurs centaines de ko de texte.

Merci

6 réponses

1 2 3 4
Avatar
espie
In article ,
James Kanze wrote:
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*.


Il le fait, en revanche. Parce que comment sait-il que sqrt(7)
renvoie toujours la même valeur ?


Parce qu'il a une boule de cristal!

sqrt fait partie de la bibliotheque standard: avec les bonnes
incantations, genre #include <cmath>, le compilateur est en droit
de faire toute la magie qu'il veut, meme si ce ne sont pas des
choses exprimables en C++ portable.

En particulier, le compilateur peut tres bien savoir qu'il s'agit
d'une `vraie' fonction, et optimiser en consequence.


Avatar
Franck Branjonneau
Sylvain Togni <"sylvain.togni at visionobjects.com"> écrivait:

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é.


Moi, un getteur non const j'appelle ça un setteur.

--
Franck Branjonneau

Avatar
James Kanze
On Mar 20, 11:20 am, Sylvain Togni <"sylvain.togni at
visionobjects.com"> wrote:
James Kanze wrote:
Un petit essai (pas très rigueureux) montre que le const fait
une différence et avec g++ et avec Sun CC sous Solaris, et avec
g++ sous Linux. Essaie donc :

double const d = 1.0009 ;
double tot1 = 1.0 ;
double tot2 = 1.0 ;
for ( int i = 0 ; i < 1000000000 ; ++ i ) {
f( d ) ;
tot1 += 2.0 * d + 1.0 ;
tot2 += 3.0 * d + 2.0 ;
}

Avec « void f( double const& ) ». Puis sans le const sur d.
Les temps sont bien différents.


C'est vrai que dans ce genre de situations le const peut
faire une différence. Mais sont-elles vraiment courantes ?
Tu passes souvent des doubles par référence constante ?


Quand j'instancie un template ?

En fait, je crois qu'il s'agit plutôt d'une convention. Remplace
le double par std::complex< double >, par exemple, et il y a de
fortes chances que tu le passes de temps en temps par référence
(or que toutes les fonctions en sont inline, et un bon
compilateur génèrera souvent du code comme si tu avais deux
doubles).

Aussi, bizarrement, j'ai essayé ce code avec 3 compilateurs
différents et jamais la version const n'a gagné.

non-const const
-------------------------------------------------------
VC6 13.8s 13.8s
VC8 2.2s 2.2s
GCC 3.4.4 cygming 10.8s 11.8s
-------------------------------------------------------


C'est très bizarre, parce qu'un de mes tests, c'était bien g++
(4.1.0) sous Linux. Sur un PC donc, et où je m'attendrais à
exactement les mêmes résultats que sous Windows. Est-ce que tu
es sûr 1) d'avoir compilé avec -O3, et 2) d'avoir mis f dans une
unité de traduction compilée à part. (g++ inline s'il voit la
définition, même si toi tu ne l'as pas démandé.)

- VC6 ne fait aucune optimisation, en const comme en
non-const et génère strictement le même code assembleur.

- VC8 fait une optimisation globale (j'ai pourtant mi la
définition de f dans une unité à part), supprime l'appel
à f et pré-calcul les deux incréments, en const comme
en non-const.

- GCC pré-calcul les deux incréments seulement en const,
effectivement, mais bizarrement cela se traduit par une
vitesse moindre de la version avec const (Vive les
architectures modernes ;-).


C'est bizarre quand même. A priori, vue les temps (surtout la
différence entre VC8 et les autres), ce que tu mesures
réelement, c'est le temps d'appel d'une fonction (et les
différences ne reflète que la manque de précision dans les
mesures). J'ai eu un effet semblable dans mon premier essai, où
je n'avais qu'une seule expression « tot += 2.1 * d ». Mais je
le trouve quand même étonnant que j'arrive à voir une différence
nette (15-20%, systèmatique) sur PC sous Linux. Est-ce qu'il y a
une différence aussi importante dans la séquence d'un appel de
fonction, due à une API différente ? (Si quelqu'un a accès à
une machine dual-boot, ça serait intéressant de voir les mesures
avec la même version de g++, une fois sous Windows, une fois
sous Linux.)

De toute façon, je crois qu'on peut bien dire que dans la
plupart des programmes, la différence ne sera pas importante, et
qu'on ne doit pas faire la décision d'office sur la base des
performances. Si par la suite, il y a un problème de
performance, et qu'on ne met pas le const d'office, on peut
toujours l'ajouter, histoire de voir. Si ça rapporte, on le
laisse (avec un commentaire). Sinon, le coût de l'essai a quand
même était minimal. (Moins même que d'essayer avec f() inline.)

--
James Kanze (GABI Software) email:
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
Sylvain Togni
James Kanze wrote:

Un petit essai (pas très rigueureux) montre que le const fait
une différence et avec g++ et avec Sun CC sous Solaris, et avec
g++ sous Linux. Essaie donc :

double const d = 1.0009 ;
double tot1 = 1.0 ;
double tot2 = 1.0 ;
for ( int i = 0 ; i < 1000000000 ; ++ i ) {
f( d ) ;
tot1 += 2.0 * d + 1.0 ;
tot2 += 3.0 * d + 2.0 ;
}

Avec « void f( double const& ) ». Puis sans le const sur d.
Les temps sont bien différents.


Aussi, bizarrement, j'ai essayé ce code avec 3 compilateurs
différents et jamais la version const n'a gagné.

non-const const
-------------------------------------------------------
VC6 13.8s 13.8s
VC8 2.2s 2.2s
GCC 3.4.4 cygming 10.8s 11.8s
-------------------------------------------------------


C'est très bizarre, parce qu'un de mes tests, c'était bien g++
(4.1.0) sous Linux. Sur un PC donc, et où je m'attendrais à
exactement les mêmes résultats que sous Windows. Est-ce que tu
es sûr 1) d'avoir compilé avec -O3, et 2) d'avoir mis f dans une
unité de traduction compilée à part. (g++ inline s'il voit la
définition, même si toi tu ne l'as pas démandé.)


Oui, j'ai mis la fonction f (vide) dans une unité compilée
à part, et j'ai utilisé les options d'optimisation maximales
des 3 compilateurs.

L'appel à f prend 80% du temps environ, c'est pour cela que
VC8, qui l'a supprimée grâce à son analyse globale, est bien
meilleur.

Quant à GCC, je pense que c'est par un malheureux hasard que
sur ma machine la version non-const est plus rapide. Un coup
d'oeil au code assembleur montre que la boucle avec le const
contient 2 fois moins d'instructions, mais sur les
architectures modernes moins d'instructions ne veut pas
forcément dire plus rapide.

De toute façon, je crois qu'on peut bien dire que dans la
plupart des programmes, la différence ne sera pas importante, et
qu'on ne doit pas faire la décision d'office sur la base des
performances. Si par la suite, il y a un problème de
performance, et qu'on ne met pas le const d'office, on peut
toujours l'ajouter, histoire de voir. Si ça rapporte, on le
laisse (avec un commentaire). Sinon, le coût de l'essai a quand
même était minimal. (Moins même que d'essayer avec f() inline.)


Oui, et on peut aussi dire qu'un bon compilateur/optimisateur
vaut mieux que mille consts.

--
Sylvain Togni



Avatar
Jean-Marc Bourguet
Sylvain Togni <"sylvain.togni at visionobjects.com"> writes:

Quant à GCC, je pense que c'est par un malheureux hasard que
sur ma machine la version non-const est plus rapide. Un coup
d'oeil au code assembleur montre que la boucle avec le const
contient 2 fois moins d'instructions, mais sur les
architectures modernes moins d'instructions ne veut pas
forcément dire plus rapide.


Voir -mtune, -march

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

Avatar
Gabriel Dos Reis
"" writes:

| Bonsoir,
|
| Est-on assuré que les éléments d'un std::vector se suivent en mémoire?

Oui.

-- Gaby
1 2 3 4