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

[stl] une map de list

16 réponses
Avatar
Bruno Causse
bonjour,

est que cette conception est valide (pseudo code c++)


typedef std::list < A > tList_A;
typedef std::map< const unsigned long long hash_code, tList_A> tMap_A;

class B{
tMap_A = my_map;
A tab[];
.../...

void add(const unsigned long long hash_code);
void restore(const unsigned long long hash_code);
}


/* sauvegarde d'objets de la table dans une liste
1) existante == rewrite
2) absente == creation
*/
void B::add(const unsigned long long hash_code) {

tList_A my_list;

/*creation d'une liste a partir du hash_code
par copie des objets A contenu dans tab

genre:
for(...)
my_list.push_back(tab[...]); //j'ai une copie

*/
initialise(my_list, hash_code);

my_map.erase(hash_code);
my_map.push_back(my_list); //je supose que j'ai une copie :-(

}

/* reecrit les objets dans la table */
void B::restore(const unsigned long long hash_code) {

tMap_A::iterator iter_map = my_map.find(hash_code);
if(iter_map != my_map.end()) {
tList_A& my_list = iter_map->second; //pas de copie
for(tList_A::const_iterator iter_list = my_list.begin(); iter_list !=
my_list.end(); iter_list++)
tab[...] = *iter_list;
}

my_map.clear(); //on efface tout
}

la gestion des "copies des objets A" (creation, supression, copie, ...) la
stl s'en charge?

6 réponses

1 2
Avatar
James Kanze
On Apr 12, 9:55 am, Fabien LE LEZ wrote:
On Thu, 12 Apr 2007 09:34:35 +0200, Yann Renard
:

y a-t-il un moyen de déclarer un
entier 64 bits de manière standard ?


Non. Il n'y a pas moyen de déclarer un entier de N bits de manière
standard, quelque soit N.



Avatar
James Kanze
On Apr 12, 9:55 am, Fabien LE LEZ wrote:
On Thu, 12 Apr 2007 09:34:35 +0200, Yann Renard
:

y a-t-il un moyen de déclarer un
entier 64 bits de manière standard ?


Non. Il n'y a pas moyen de déclarer un entier de N bits de manière
standard, quelque soit N.


En C99, il y a bien long long (qui a au moins 64 bits), et
int64_t (qui a exactement 64 bits, s'il existe). Tous les deux
qui ont été adopté en C++, pour la prochaine version, et tous
les deux qui sont supportés en fait par tous les compilateurs
actuels (à ma connaissance, en tout cas).

--
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
James Kanze
On Apr 12, 9:13 pm, Franck Branjonneau wrote:
"James Kanze" écrivait:

Attention long long n'est pas standard.


Mais si. Il n'est pas dans ISO 14882:2003,


N'est-ce pas contradictoire ?


Seulement si tu crois que le monde commence et termine avec C++.

mais il fait partie de la norme C (ISO 9899:1999), et il a
été adopté par le comité C++ pour la prochaine version de la
norme C++.


Ma machine à voyager dans le temps est en panne, je n'arrrive
pas à me projeter en 0x.


Je sais ce qui a été discuté, et ce qui a été voté. Certes, le
comité pourrait encore voter de l'enveler, après l'avoir voter
de l'accepter, mais réalistiquement, la probabilité que ça se
passe me semble quasiment nulle. D'autant plus que, comme j'ai
dit, tous les compilateurs l'ont déjà implémenté.

Et je ne connais pas de compilateur C++ actuel qui ne le supporte pas d éjà.


En le documentant comme un extension ?


Parfois, peut-être. La plupart du temps, je crois, ils le
traitent déjà comme faisant partie de la norme.

echo "int main() { long long ll; }" | g++ -x c++ --std=c++98 --pedantic -


Si tu démandes exprès de ne pas l'avoir...

(Je sais : autrefois, avec g++, il fallait le --pedantic, parce
que le compilateur activait trop d'extensions propre à g++ par
défaut. Mais ça fait un moment que je ne m'en sers pas dans la
production, parce que le compilateur actuel est assez rigueureux
sans l'option, et qu'il vaut réelement ce que dit son nom.)

my_map.push_back(my_list); //je supose que j'ai une copie :-(


Une copie ? Ça n'a pas de sens ! où sont le "front" et le
"back" d'un arbre, une std::map<> ?


Je crois qu'il parle d'une copie de la liste.


Oui. Et moi je parle de std::map<>::push_back !


Alors, il y a bien une copie.

[...]
Mais c'est à peu près la limite. J'aurais une tendance à écrire mon code
comme si std::list n'avait pas de constructeur de copie.


Ça n'entre pas dans la catégorie des optimisations prématurées ?


Comme j'ai expliqué par la suite, ça entre plutôt dans la
catégorie de « qu'est-ce que c'est qu'une collection ». (Et
que la distinction n'est pas tout nette.) Comme règle gènerale
(qui accepte bien des exceptions) : un type qui contient des
fonctions membre non const a une identité, et des types qui ont
une idéntité ne supportent pas l'affectation.

(des « building blocks », mais je ne trouve pas d'expression
équivalente en français),


Briques ?


C'est le mieux que je trouve aussi.

ou tList_A const & my_list(iter_map->second);
La syntaxe d'initialisation utilisant le symbole = implique une copi e.


Pas quand on initialise une référence.


Je sais maintenant pourquoi, avant de me relire, j'avais mis des parenth èses
autour de cette phrase ;-)

(Pas forcément autrement non plus.)


Vraiment ?


La norme donne explicitement le droit au compilateur de se
passer de la copie, et prèsque tous le font, au moins dans
certains cas. (Mais même si la copie ne se fait pas, le
compilateur est obligé de vérifier que la copie serait légale.)

Essaie quelque chose comme le suivant :

class A
{
public :
A() {}
private :
A( A const& ) { std::cout << "coucou : on me copie" <<
std::endl ; }
} ;

int
main()
{
A a = A() ;
return 0 ;
}

Tu as (ou dois avoir) une erreur de compilation, parce que le
cosntructeur de copie est privé. Maintenant, mets le "private:"
en commentaire. Le code se compile, mais lors de l'exécution (au
moins avec les compilateurs auquels j'ai accès), pas de message
du constructeur de copie -- la copie n'a pas eu lieu.

Pire : supprimer la définition du constructeur dans ce cas-là,
et le code se compile et linke aussi bien qu'avant. (D'accord,
c'est un comportement indéfini, et la norme n'exige pas de
diagnostique. Mais on en aimerait un quand même.)

--
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
James Kanze
On Apr 11, 10:22 pm, "Bruno Causse" wrote:
"James Kanze" a écrit dans le message de news:

On Apr 10, 11:53 pm, "Bruno Causse" wrote:

Mais il ne serait pas mal que tu nous expliques exactement ce
que tu essaies de faire. Parce que ce que tu nous montre à l'air
un peu lourd.


j'ai une table de position (jeux de damier, echec, dame, othello...)
implementée sous une forme de table de hashage (une position est repres entée
par une clef (24 bits) et un verrou (40bits)).

a partir de cette table je peux rejouer la meilleure variation/refutation
trouvée. Malheuresement cette table n'est pas infinie (2^24) et des
positions importantes peuvent etre reecrite. Je souhaite temporairement
sauvegarder celles ci, pour pouvoir les restaurer.


Et quel est le rôle de la liste, là-dedans ?

Le problème de base, c'est que std::list est une structure
extrèmement peu performante, surtout en ce qui concerne
l'utilisation de la mémoire. Au moins d'avoir absolument besoin
de l'insertion et de l'effacement rapide au milieu d'une
collection avec beaucoup d'éléments, il vaut mieux en général
utiliser std::deque ou std::vector.

Dans la pratique, std::map ne copie ni n'affecte les éléments
une fois qu'ils y sont. Il m'est arrivé donc d'utiliser des
std::map< xxx, std::map > ou des std::map< xxx, std::vector >
sans trop de problèmes de lourdeur, en m'assurant que j'insérais
toujours un map ou un vecteur vide, et que j'insérais ensuite
dans l'élément dans le map. Typiquement, avec quelque chose du
genre :
map[ xxx ].push_back( nouvelElement ) ;
ou
map[ xxx ].insert( SubmapType::value_type( yyy, zzz ) ) ;
Je ne suis pas un acharné sur les performance, loin de ça, mais
je n'aime pas trop l'idée d'une copie profonde d'une std::list.
(J'ai eu le cas, une fois, où j'avais une fonction qui renvoyait
mon équivalent pré-norme d'une std::list, avec 60000 éléments.
Ça prenait à peu près 20 sécondes sur la machine à l'époque. Vue
que je ne le faisais que 4 fois dans une application qui
tournait bien plus de trois quarts d'heures, ce n'était pas
grave, mais ça donne à penser quand même.)


le nombre de mouvements (coups) possibles pour une position est <32
une variation (suite de coups) est limité par la puissance des machine a <40
donc au max une map de 32 list de 40 elements (== aucun probleme de perf).


OK. En fait, les listes sont assez courtes.

--
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
Fabien LE LEZ
On Thu, 12 Apr 2007 21:40:20 +0200, "Bruno Causse"
:

betement, c'est la structure qui me semble la plus "naturelle".


Barf... Généralement, quand on parle d'une "liste" en langage
"quotidien", ça correspond au terme informatique "tableau" -- on n'a
pas forcément besoin de la structure de liste chaînée.

Et la classe canonique pour un tableau, c'est std::vector<>. On
s'intéresse à d'autres classes quand, pour une raison ou une autre,
vector<> ne convient pas.

Avatar
James Kanze
On Apr 13, 10:25 am, Fabien LE LEZ wrote:
On Thu, 12 Apr 2007 21:40:20 +0200, "Bruno Causse"
:

betement, c'est la structure qui me semble la plus "naturelle".


Barf... Généralement, quand on parle d'une "liste" en langage
"quotidien", ça correspond au terme informatique "tableau" -- on n'a
pas forcément besoin de la structure de liste chaînée.


Pas forcément, mais... J'ai mis beaucoup de temps moi-même à me
rendre compte qu'il faut disassocier la structure logique du nom
de la classe qui l'implément. Quand j'ai une liste, je régarde
d'abord quelles sont les opérations dont j'aurais besoin cette
fois-ci, et choisis la collection en fonction de ça. (Peut-être
j'en parle justement parce qu'il m'a fallu tellement de temps de
m'en rendre compte.)

Et la classe canonique pour un tableau, c'est std::vector<>. On
s'intéresse à d'autres classes quand, pour une raison ou une autre,
vector<> ne convient pas.


En effet. vector<> a l'avantage d'être la plus légère des
collections. C'est donc celle dont je me sers systèmatiquement,
au moins que j'ai une raison particulière d'en choisir une
autre.

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


1 2