int main()
{
const std::vector<int> & v = get_test().get_vector();
std::cout << v.size() << 'n';
}
g++ m'affiche 3, VC++ 0. Qui a raison ?
Bonjour,
D'après ce que je sais, si une référence constante est initialisée avec un
objet temporaire, on a la garantie que l'objet temporaire persiste tant
que
la référence existe. OK.
Question : et si c'est une donnée membre d'un objet temporaire :
#include <vector>
#include <iostream>
class Test
{
public:
Test()
{
vect.push_back( 1 );
vect.push_back( 2 );
vect.push_back( 3 );
}
const std::vector<int> & get_vector() const
{
return this->vect;
}
private:
std::vector<int> vect;
};
Test get_test()
{
return Test();
}
int main()
{
const std::vector<int> & v = get_test().get_vector();
std::cout << v.size() << 'n';
}
g++ m'affiche 3, VC++ 0. Qui a raison ?
--
Aurélien REGAT-BARREL
int main()
{
const std::vector<int> & v = get_test().get_vector();
std::cout << v.size() << 'n';
}
g++ m'affiche 3, VC++ 0. Qui a raison ?
Bonjour,
D'après ce que je sais, si une référence constante est initialisée avec un
objet temporaire, on a la garantie que l'objet temporaire persiste tant
que
la référence existe. OK.
Question : et si c'est une donnée membre d'un objet temporaire :
#include <vector>
#include <iostream>
class Test
{
public:
Test()
{
vect.push_back( 1 );
vect.push_back( 2 );
vect.push_back( 3 );
}
const std::vector<int> & get_vector() const
{
return this->vect;
}
private:
std::vector<int> vect;
};
Test get_test()
{
return Test();
}
int main()
{
const std::vector<int> & v = get_test().get_vector();
std::cout << v.size() << 'n';
}
g++ m'affiche 3, VC++ 0. Qui a raison ?
--
Aurélien REGAT-BARREL
int main()
{
const std::vector<int> & v = get_test().get_vector();
std::cout << v.size() << 'n';
}
g++ m'affiche 3, VC++ 0. Qui a raison ?
Bonjour,
D'après ce que je sais, si une référence constante est initialisée avec un
objet temporaire, on a la garantie que l'objet temporaire persiste tant
que
la référence existe. OK.
Question : et si c'est une donnée membre d'un objet temporaire :
#include <vector>
#include <iostream>
class Test
{
public:
Test()
{
vect.push_back( 1 );
vect.push_back( 2 );
vect.push_back( 3 );
}
const std::vector<int> & get_vector() const
{
return this->vect;
}
private:
std::vector<int> vect;
};
Test get_test()
{
return Test();
}
int main()
{
const std::vector<int> & v = get_test().get_vector();
std::cout << v.size() << 'n';
}
g++ m'affiche 3, VC++ 0. Qui a raison ?
--
Aurélien REGAT-BARREL
J'ai modifié mon test pour voir si ma référence ne désignait
pas un objet détruit, et c'est le cas. Je suppose juste que le
std::vector de g++ ne met pas son size à 0 lors de sa
destruction, contrairement à celui de VC++.
class A
{
public:
~A()
{
std::cout << "~A()n";
}
};
class Test
{
public:
Test() : vect( 3 )
{
}
const std::vector<A> & get_vector() const
{
return this->vect;
}
private:
std::vector<A> vect;
};
Test get_test()
{
return Test();
}
int main()
{
const std::vector<A> & v = get_test().get_vector();
std::cout << "Taille = " << v.size() << 'n';
}
ce qui m'affiche:
~A()
~A()
~A()
~A()
Taille = 0
Par contre je pige pas d'où sort le 4° (le premier en fait)
objet A détruit.
J'ai modifié mon test pour voir si ma référence ne désignait
pas un objet détruit, et c'est le cas. Je suppose juste que le
std::vector de g++ ne met pas son size à 0 lors de sa
destruction, contrairement à celui de VC++.
class A
{
public:
~A()
{
std::cout << "~A()n";
}
};
class Test
{
public:
Test() : vect( 3 )
{
}
const std::vector<A> & get_vector() const
{
return this->vect;
}
private:
std::vector<A> vect;
};
Test get_test()
{
return Test();
}
int main()
{
const std::vector<A> & v = get_test().get_vector();
std::cout << "Taille = " << v.size() << 'n';
}
ce qui m'affiche:
~A()
~A()
~A()
~A()
Taille = 0
Par contre je pige pas d'où sort le 4° (le premier en fait)
objet A détruit.
J'ai modifié mon test pour voir si ma référence ne désignait
pas un objet détruit, et c'est le cas. Je suppose juste que le
std::vector de g++ ne met pas son size à 0 lors de sa
destruction, contrairement à celui de VC++.
class A
{
public:
~A()
{
std::cout << "~A()n";
}
};
class Test
{
public:
Test() : vect( 3 )
{
}
const std::vector<A> & get_vector() const
{
return this->vect;
}
private:
std::vector<A> vect;
};
Test get_test()
{
return Test();
}
int main()
{
const std::vector<A> & v = get_test().get_vector();
std::cout << "Taille = " << v.size() << 'n';
}
ce qui m'affiche:
~A()
~A()
~A()
~A()
Taille = 0
Par contre je pige pas d'où sort le 4° (le premier en fait)
objet A détruit.
Je ne vois toujours pas où ton test vérifie le nombre de copies
qui existe de l'object en question (un std::vector, n'oublions
pas).
Plus intéressant serait de rendre le membre vect public, et
d'écrire :
std::vector<A> const& v = get_test().vect ;
Là, j'avoue ne pas être très sur de l'effet possible sur la
durée de vie du temporaire de type Test. Selon la norme,
l'implémentation a deux choix :
-- lier la référence à l'objet que représente l'expression
temporaire (le « rvalue »), ou
-- faire un temporaire du type de l'expression
d'initialisation (par exemple, de la classe dérivée, même si
on lie à une référence de type classe de base), et lier
l'expression au temporaire.
Dans les deux cas, le compilateur a droit à lier à un
sous-objet.
Note en revanche ici que le type de l'expression
d'initialisation est bien std::vector<A>, et NON Test. Je ne
suis pas vraiment sûr de l'intention ici, mais je ne vois rien
dans le texte de la norme qui donne au compilateur le droit de
prolonger la durée de vie du temporaire Test (qui lui n'est lié
à aucune référence). Et je ne vois pas comment le compilateur
pourrait detruire le Test sans en detruire le sous-objet vect.
Du coup, le seul alternatif que je vois que lui est ouvert est
de profiter du deuxième point ci-dessus, de faire une copie de
vect, et de lier la copie à la référence (en lui donnant la
durée de vie de la référence).
Par contre je pige pas d'où sort le 4° (le premier en fait)
objet A détruit.
Tu as bien initialisé le vecteur avec quelque chose, non.
L'initialisation des éléments d'un vector se fait toujours au
moyen d'un constructeur de copie. Alors, il faut bien un objet
qu'on copie. Ça fait donc trois éléments dans le vecteur, et un
objet (temporaire) qu'on copie pour les initialiser, donc,
quatre objets.
Je ne vois toujours pas où ton test vérifie le nombre de copies
qui existe de l'object en question (un std::vector, n'oublions
pas).
Plus intéressant serait de rendre le membre vect public, et
d'écrire :
std::vector<A> const& v = get_test().vect ;
Là, j'avoue ne pas être très sur de l'effet possible sur la
durée de vie du temporaire de type Test. Selon la norme,
l'implémentation a deux choix :
-- lier la référence à l'objet que représente l'expression
temporaire (le « rvalue »), ou
-- faire un temporaire du type de l'expression
d'initialisation (par exemple, de la classe dérivée, même si
on lie à une référence de type classe de base), et lier
l'expression au temporaire.
Dans les deux cas, le compilateur a droit à lier à un
sous-objet.
Note en revanche ici que le type de l'expression
d'initialisation est bien std::vector<A>, et NON Test. Je ne
suis pas vraiment sûr de l'intention ici, mais je ne vois rien
dans le texte de la norme qui donne au compilateur le droit de
prolonger la durée de vie du temporaire Test (qui lui n'est lié
à aucune référence). Et je ne vois pas comment le compilateur
pourrait detruire le Test sans en detruire le sous-objet vect.
Du coup, le seul alternatif que je vois que lui est ouvert est
de profiter du deuxième point ci-dessus, de faire une copie de
vect, et de lier la copie à la référence (en lui donnant la
durée de vie de la référence).
Par contre je pige pas d'où sort le 4° (le premier en fait)
objet A détruit.
Tu as bien initialisé le vecteur avec quelque chose, non.
L'initialisation des éléments d'un vector se fait toujours au
moyen d'un constructeur de copie. Alors, il faut bien un objet
qu'on copie. Ça fait donc trois éléments dans le vecteur, et un
objet (temporaire) qu'on copie pour les initialiser, donc,
quatre objets.
Je ne vois toujours pas où ton test vérifie le nombre de copies
qui existe de l'object en question (un std::vector, n'oublions
pas).
Plus intéressant serait de rendre le membre vect public, et
d'écrire :
std::vector<A> const& v = get_test().vect ;
Là, j'avoue ne pas être très sur de l'effet possible sur la
durée de vie du temporaire de type Test. Selon la norme,
l'implémentation a deux choix :
-- lier la référence à l'objet que représente l'expression
temporaire (le « rvalue »), ou
-- faire un temporaire du type de l'expression
d'initialisation (par exemple, de la classe dérivée, même si
on lie à une référence de type classe de base), et lier
l'expression au temporaire.
Dans les deux cas, le compilateur a droit à lier à un
sous-objet.
Note en revanche ici que le type de l'expression
d'initialisation est bien std::vector<A>, et NON Test. Je ne
suis pas vraiment sûr de l'intention ici, mais je ne vois rien
dans le texte de la norme qui donne au compilateur le droit de
prolonger la durée de vie du temporaire Test (qui lui n'est lié
à aucune référence). Et je ne vois pas comment le compilateur
pourrait detruire le Test sans en detruire le sous-objet vect.
Du coup, le seul alternatif que je vois que lui est ouvert est
de profiter du deuxième point ci-dessus, de faire une copie de
vect, et de lier la copie à la référence (en lui donnant la
durée de vie de la référence).
Par contre je pige pas d'où sort le 4° (le premier en fait)
objet A détruit.
Tu as bien initialisé le vecteur avec quelque chose, non.
L'initialisation des éléments d'un vector se fait toujours au
moyen d'un constructeur de copie. Alors, il faut bien un objet
qu'on copie. Ça fait donc trois éléments dans le vecteur, et un
objet (temporaire) qu'on copie pour les initialiser, donc,
quatre objets.
int main()
{
const std::vector<A> & v = get_test().get_vector();
std::cout << "Taille = " << v.size() << 'n';
}
Je ne vois toujours pas où ton test vérifie le nombre de
copies qui existe de l'object en question (un std::vector,
n'oublions pas).
Une fois le programme exécuté, j'ai 4 objets A détruits avant
le cout, et aucun après. J'en déduis que mon vecteur a été
détruit avant l'appel à cout, et qu'il n'en n'existe aucune
copie (aucun affichage par la suite).
Par contre je pige pas d'où sort le 4° (le premier en fait)
objet A détruit.
Tu as bien initialisé le vecteur avec quelque chose, non.
L'initialisation des éléments d'un vector se fait toujours au
moyen d'un constructeur de copie. Alors, il faut bien un objet
qu'on copie. Ça fait donc trois éléments dans le vecteur, et
un objet (temporaire) qu'on copie pour les initialiser, donc,
quatre objets.
Je pensais que vector faisait directement 3 new de placement.
En fait, je pige pas pourquoi il utilise la recopie. Ca lui
fait créer un temporaire en plus, non ?
int main()
{
const std::vector<A> & v = get_test().get_vector();
std::cout << "Taille = " << v.size() << 'n';
}
Je ne vois toujours pas où ton test vérifie le nombre de
copies qui existe de l'object en question (un std::vector,
n'oublions pas).
Une fois le programme exécuté, j'ai 4 objets A détruits avant
le cout, et aucun après. J'en déduis que mon vecteur a été
détruit avant l'appel à cout, et qu'il n'en n'existe aucune
copie (aucun affichage par la suite).
Par contre je pige pas d'où sort le 4° (le premier en fait)
objet A détruit.
Tu as bien initialisé le vecteur avec quelque chose, non.
L'initialisation des éléments d'un vector se fait toujours au
moyen d'un constructeur de copie. Alors, il faut bien un objet
qu'on copie. Ça fait donc trois éléments dans le vecteur, et
un objet (temporaire) qu'on copie pour les initialiser, donc,
quatre objets.
Je pensais que vector faisait directement 3 new de placement.
En fait, je pige pas pourquoi il utilise la recopie. Ca lui
fait créer un temporaire en plus, non ?
int main()
{
const std::vector<A> & v = get_test().get_vector();
std::cout << "Taille = " << v.size() << 'n';
}
Je ne vois toujours pas où ton test vérifie le nombre de
copies qui existe de l'object en question (un std::vector,
n'oublions pas).
Une fois le programme exécuté, j'ai 4 objets A détruits avant
le cout, et aucun après. J'en déduis que mon vecteur a été
détruit avant l'appel à cout, et qu'il n'en n'existe aucune
copie (aucun affichage par la suite).
Par contre je pige pas d'où sort le 4° (le premier en fait)
objet A détruit.
Tu as bien initialisé le vecteur avec quelque chose, non.
L'initialisation des éléments d'un vector se fait toujours au
moyen d'un constructeur de copie. Alors, il faut bien un objet
qu'on copie. Ça fait donc trois éléments dans le vecteur, et
un objet (temporaire) qu'on copie pour les initialiser, donc,
quatre objets.
Je pensais que vector faisait directement 3 new de placement.
En fait, je pige pas pourquoi il utilise la recopie. Ca lui
fait créer un temporaire en plus, non ?
D'après ce que je sais, si une référence constante est initialisée avec un
objet temporaire, on a la garantie que l'objet temporaire persiste tant
que
la référence existe. OK.
D'après ce que je sais, si une référence constante est initialisée avec un
objet temporaire, on a la garantie que l'objet temporaire persiste tant
que
la référence existe. OK.
D'après ce que je sais, si une référence constante est initialisée avec un
objet temporaire, on a la garantie que l'objet temporaire persiste tant
que
la référence existe. OK.
D'après ce que je sais, si une référence constante est
initialisée avec un objet temporaire, on a la garantie que
l'objet temporaire persiste tant que la référence existe.
OK.
Je ne savais pas ca...
Est ce que le code suivant est valide dans ce cas :
const std::string& foo() { return "bar"; }
int main() { std::cout << foo(); }
D'après ce que je sais, si une référence constante est
initialisée avec un objet temporaire, on a la garantie que
l'objet temporaire persiste tant que la référence existe.
OK.
Je ne savais pas ca...
Est ce que le code suivant est valide dans ce cas :
const std::string& foo() { return "bar"; }
int main() { std::cout << foo(); }
D'après ce que je sais, si une référence constante est
initialisée avec un objet temporaire, on a la garantie que
l'objet temporaire persiste tant que la référence existe.
OK.
Je ne savais pas ca...
Est ce que le code suivant est valide dans ce cas :
const std::string& foo() { return "bar"; }
int main() { std::cout << foo(); }
Bonjour,
D'après ce que je sais, si une référence constante est initialisée avec un
objet temporaire, on a la garantie que l'objet temporaire persiste tant que
la référence existe. OK.
J'aimerais bien savoir d'ou tu tiens ça.
Question : et si c'est une donnée membre d'un objet temporaire :
#include <vector>
#include <iostream>
class Test
{
public:
Test()
{
vect.push_back( 1 );
vect.push_back( 2 );
vect.push_back( 3 );
}
const std::vector<int> & get_vector() const
{
return this->vect;
}
private:
std::vector<int> vect;
};
Test get_test()
{
return Test();
}
int main()
{
const std::vector<int> & v = get_test().get_vector();
std::cout << v.size() << 'n';
}
g++ m'affiche 3, VC++ 0. Qui a raison ?
En rajoutant le destructeur de Test
Bonjour,
D'après ce que je sais, si une référence constante est initialisée avec un
objet temporaire, on a la garantie que l'objet temporaire persiste tant que
la référence existe. OK.
J'aimerais bien savoir d'ou tu tiens ça.
Question : et si c'est une donnée membre d'un objet temporaire :
#include <vector>
#include <iostream>
class Test
{
public:
Test()
{
vect.push_back( 1 );
vect.push_back( 2 );
vect.push_back( 3 );
}
const std::vector<int> & get_vector() const
{
return this->vect;
}
private:
std::vector<int> vect;
};
Test get_test()
{
return Test();
}
int main()
{
const std::vector<int> & v = get_test().get_vector();
std::cout << v.size() << 'n';
}
g++ m'affiche 3, VC++ 0. Qui a raison ?
En rajoutant le destructeur de Test
Bonjour,
D'après ce que je sais, si une référence constante est initialisée avec un
objet temporaire, on a la garantie que l'objet temporaire persiste tant que
la référence existe. OK.
J'aimerais bien savoir d'ou tu tiens ça.
Question : et si c'est une donnée membre d'un objet temporaire :
#include <vector>
#include <iostream>
class Test
{
public:
Test()
{
vect.push_back( 1 );
vect.push_back( 2 );
vect.push_back( 3 );
}
const std::vector<int> & get_vector() const
{
return this->vect;
}
private:
std::vector<int> vect;
};
Test get_test()
{
return Test();
}
int main()
{
const std::vector<int> & v = get_test().get_vector();
std::cout << v.size() << 'n';
}
g++ m'affiche 3, VC++ 0. Qui a raison ?
En rajoutant le destructeur de Test
Ce genre de pratique est à bannir.
D'une manière générale il est fortement déconseillé de retourner une
référence ou un pointeur sur une donnée membre (ce qui est fait dans
get_vector) car on a plus aucune visibilité sur la durée de vie de l'objet
retourné.
Ce genre de pratique est à bannir.
D'une manière générale il est fortement déconseillé de retourner une
référence ou un pointeur sur une donnée membre (ce qui est fait dans
get_vector) car on a plus aucune visibilité sur la durée de vie de l'objet
retourné.
Ce genre de pratique est à bannir.
D'une manière générale il est fortement déconseillé de retourner une
référence ou un pointeur sur une donnée membre (ce qui est fait dans
get_vector) car on a plus aucune visibilité sur la durée de vie de l'objet
retourné.
Ce genre de pratique est à bannir.
D'une manière générale il est fortement déconseillé de retourner une
référence ou un pointeur sur une donnée membre (ce qui est fait dans
get_vector) car on a plus aucune visibilité sur la durée de vie de l'objet
retourné.
C'est quand même fait à plein d'endroits par la STL...
Par exemple l'operateur constant [] de vector retourne une référence
constante sur l'objet. Tu trouves que c'est une mauvaise technique de
programmation ?
Dans le cas des collections effectivement il faut mieux que la classe
Ce genre de pratique est à bannir.
D'une manière générale il est fortement déconseillé de retourner une
référence ou un pointeur sur une donnée membre (ce qui est fait dans
get_vector) car on a plus aucune visibilité sur la durée de vie de l'objet
retourné.
C'est quand même fait à plein d'endroits par la STL...
Par exemple l'operateur constant [] de vector retourne une référence
constante sur l'objet. Tu trouves que c'est une mauvaise technique de
programmation ?
Dans le cas des collections effectivement il faut mieux que la classe
Ce genre de pratique est à bannir.
D'une manière générale il est fortement déconseillé de retourner une
référence ou un pointeur sur une donnée membre (ce qui est fait dans
get_vector) car on a plus aucune visibilité sur la durée de vie de l'objet
retourné.
C'est quand même fait à plein d'endroits par la STL...
Par exemple l'operateur constant [] de vector retourne une référence
constante sur l'objet. Tu trouves que c'est une mauvaise technique de
programmation ?
Dans le cas des collections effectivement il faut mieux que la classe