ajout d'un objet dans une et destructeur
Le
Benoit Izac

Bonjour,
=
#include <map>
#include <sstream>
#include <string>
#include <iostream>
int nb_constr = 0;
int nb_constr_param = 0;
int nb_destr = 0;
class test {
public:
test();
test(const int&);
~test();
private:
int value;
};
test::test()
{
value = -1;
std::cout << " constructor (" << value << ") ("
<< ++nb_constr << ")" << std::endl;
}
test::test(const int& i)
{
value = i;
std::cout << " constructor with param (" << value << ") ("
<< ++nb_constr_param << ")" << std::endl;
}
test::~test()
{
std::cout << " destructor (" << value << ") ("
<< ++nb_destr << ")" << std::endl;
}
int main()
{
std::map<std::string, test> m;
for (int i = 0; i < 5; ++i) {
std::cout << "creation" << std::endl;
test t(i);
std::string s;
{
std::ostringstream oss;
oss << i;
s = oss.str();
}
std::cout << "affectation" << std::endl;
m[s] = t;
std::cout << "end of loop" << std::endl;
}
return 0;
}
=
Pouvez-vous m'expliquer la magie dans « m[s] = t » ?
Je comprends le premier constructeur comme la création d'un objet test
pour y copier ensuite le contenu de t. En revanche, je ne comprends pas
les deux destructeurs qui suivent
Merci.
--
Benoit Izac
=
#include <map>
#include <sstream>
#include <string>
#include <iostream>
int nb_constr = 0;
int nb_constr_param = 0;
int nb_destr = 0;
class test {
public:
test();
test(const int&);
~test();
private:
int value;
};
test::test()
{
value = -1;
std::cout << " constructor (" << value << ") ("
<< ++nb_constr << ")" << std::endl;
}
test::test(const int& i)
{
value = i;
std::cout << " constructor with param (" << value << ") ("
<< ++nb_constr_param << ")" << std::endl;
}
test::~test()
{
std::cout << " destructor (" << value << ") ("
<< ++nb_destr << ")" << std::endl;
}
int main()
{
std::map<std::string, test> m;
for (int i = 0; i < 5; ++i) {
std::cout << "creation" << std::endl;
test t(i);
std::string s;
{
std::ostringstream oss;
oss << i;
s = oss.str();
}
std::cout << "affectation" << std::endl;
m[s] = t;
std::cout << "end of loop" << std::endl;
}
return 0;
}
=
Pouvez-vous m'expliquer la magie dans « m[s] = t » ?
Je comprends le premier constructeur comme la création d'un objet test
pour y copier ensuite le contenu de t. En revanche, je ne comprends pas
les deux destructeurs qui suivent
Merci.
--
Benoit Izac
Si tu veux tracker tous les appels à des constructeurs, il faut
y ajouter celui qui serait fourni autrement par le compilateur :
test( test const& other );
Et l'implémentation de celui qu'on a ajouté :
test::test( test const& other )
: value( other.value )
{
std::cout << " copy constructor (" << value << ") (""
<< ++nb_constr_param << ")" << std::endl;
}
(Je dirai, en passant, que dans ce genre de case, c'est souvent
utile d'y ajouter un " << this "" dans ce qu'on sort.)
Ce sont des destructions des temporaires dans std::map.
Il lui en faut deux, parce que "m[s]" est l'équivalent de
"m.insert( std::make_pair( s, test() ) )". Le premier
temporaire, c'est celui qui sert de paramètre de
`std::make_pair` ; c'est celui construit par le constructeur par
défaut. Le deuxième, c'est le membre du "std::pair" construit
(par le constructeur de copie) pour le passer comme paramètre
à std::map<>::insert. Un troisième serait construit comme partie
de l'entrée dans le map, mais celui-là n'est pas un temporaire ;
il perdurera bien au-delà de l'expression.
--
James
le 10/07/2013 à 18:33, James Kanze a écrit dans le message
Merci, j'ai bien compris le fonctionnement.
Concernant l'équivalence entre m[s] et m.insert(...), c'est garantie ou
c'est propre à l'implémentation ?
--
Benoit Izac
La norme dit simplement que "If there is no key equivalent to
x in the map, inserts value_type(x, T()) into the map."
L'implémentation triviale est:
T& operator[]( key_type const& key )
{
return *insert( value_type( key, T() ) ).first;
}
Encore que ça crée une instance de T() même si on n'en a pas
besoin. Les deux implémentations auxquels j'ai accès
n'appellent `insert` (et donc, ne créent des temporaires) que si
la clé n'est pas présent.
--
James
Je soupconne fortement que ca va se comporter de facon plus efficace
si on passe en C++2011...