il semble que tu prennes un malin plaisir à tout embrouiller dans le
post d'après ;)
Peut-être que si tu reformulais ton problème tel qu'il est réellement,
ie en montrant la classe des objets que tu veux gérer dans ton vector,
ce serait un peu plus clair.
Voici donc plusieurs exemples concrets de classes dont je désire créer un
tableau :
struct MyClass {
int nb;
MyClass() {
nb = rand();
cout << "Objet " << nb << "n";
}
~MyClass() {
cout << "Delete " << nb << "n";
}
};
Il faut que les nombres contenus dans les éléments du tableau de MyClass
soient différents (comme le ferait un "MyClass[] vec = new MyClass[]"),
ce que ne fait pas un "vector<MyClass> vec(10)".
Un autre exemple :
struct MyClass {
HANDLE hwnd;
MyClass() {
hwnd = OpenHandle();
}
~MyClass() {
CloseHandle( hwnd );
}
};
Faire
vector<MyClass> vec;
for( i=0; i<10; ++i) {
vec.push_back( MyClass() );
}
ne fonctionne pas car le handle est fermé tout de suite.
il semble que tu prennes un malin plaisir à tout embrouiller dans le
post d'après ;)
Peut-être que si tu reformulais ton problème tel qu'il est réellement,
ie en montrant la classe des objets que tu veux gérer dans ton vector,
ce serait un peu plus clair.
Voici donc plusieurs exemples concrets de classes dont je désire créer un
tableau :
struct MyClass {
int nb;
MyClass() {
nb = rand();
cout << "Objet " << nb << "n";
}
~MyClass() {
cout << "Delete " << nb << "n";
}
};
Il faut que les nombres contenus dans les éléments du tableau de MyClass
soient différents (comme le ferait un "MyClass[] vec = new MyClass[]"),
ce que ne fait pas un "vector<MyClass> vec(10)".
Un autre exemple :
struct MyClass {
HANDLE hwnd;
MyClass() {
hwnd = OpenHandle();
}
~MyClass() {
CloseHandle( hwnd );
}
};
Faire
vector<MyClass> vec;
for( i=0; i<10; ++i) {
vec.push_back( MyClass() );
}
ne fonctionne pas car le handle est fermé tout de suite.
il semble que tu prennes un malin plaisir à tout embrouiller dans le
post d'après ;)
Peut-être que si tu reformulais ton problème tel qu'il est réellement,
ie en montrant la classe des objets que tu veux gérer dans ton vector,
ce serait un peu plus clair.
Voici donc plusieurs exemples concrets de classes dont je désire créer un
tableau :
struct MyClass {
int nb;
MyClass() {
nb = rand();
cout << "Objet " << nb << "n";
}
~MyClass() {
cout << "Delete " << nb << "n";
}
};
Il faut que les nombres contenus dans les éléments du tableau de MyClass
soient différents (comme le ferait un "MyClass[] vec = new MyClass[]"),
ce que ne fait pas un "vector<MyClass> vec(10)".
Un autre exemple :
struct MyClass {
HANDLE hwnd;
MyClass() {
hwnd = OpenHandle();
}
~MyClass() {
CloseHandle( hwnd );
}
};
Faire
vector<MyClass> vec;
for( i=0; i<10; ++i) {
vec.push_back( MyClass() );
}
ne fonctionne pas car le handle est fermé tout de suite.
Cyrille "cns" Szymanski wrote:v.push_back( MyClass() ); // l'objet temporaire est alloué sur
Aïe, l'objet temporaire est détruit. Il faut donc que je ruse pour que
le destructeur ne libère pas des ressources que la copie pourrait
utiliser.
Mais dans ce cas, tu wrappes (emballe) ta "ressource" dans une classe
rien que pour ça, qui devient membre de MyClass, et dont un rôle
principal est de déterminer si, quand on passe par son destructeur, la
ressource doit être libérée.
Ca sent le pointeur quelque part (dans la nouvelle classe, je dirais),
et on me dit que ce que je raconte navigue entre les idées de pointeur
intelligent, comptage de références et singleton.
Cyrille "cns" Szymanski wrote:
v.push_back( MyClass() ); // l'objet temporaire est alloué sur
Aïe, l'objet temporaire est détruit. Il faut donc que je ruse pour que
le destructeur ne libère pas des ressources que la copie pourrait
utiliser.
Mais dans ce cas, tu wrappes (emballe) ta "ressource" dans une classe
rien que pour ça, qui devient membre de MyClass, et dont un rôle
principal est de déterminer si, quand on passe par son destructeur, la
ressource doit être libérée.
Ca sent le pointeur quelque part (dans la nouvelle classe, je dirais),
et on me dit que ce que je raconte navigue entre les idées de pointeur
intelligent, comptage de références et singleton.
Cyrille "cns" Szymanski wrote:v.push_back( MyClass() ); // l'objet temporaire est alloué sur
Aïe, l'objet temporaire est détruit. Il faut donc que je ruse pour que
le destructeur ne libère pas des ressources que la copie pourrait
utiliser.
Mais dans ce cas, tu wrappes (emballe) ta "ressource" dans une classe
rien que pour ça, qui devient membre de MyClass, et dont un rôle
principal est de déterminer si, quand on passe par son destructeur, la
ressource doit être libérée.
Ca sent le pointeur quelque part (dans la nouvelle classe, je dirais),
et on me dit que ce que je raconte navigue entre les idées de pointeur
intelligent, comptage de références et singleton.
Alors ma question est comment déplacer un objet ?
Alors ma question est comment déplacer un objet ?
Alors ma question est comment déplacer un objet ?
Ce que je veux c'est dynamiquement allouer de la mémoire (un tableau
de n objets, malloc( sizeof(MyClass)*n ) ) et instancier un objet à
chaque emplacement (new (&vec[i]) MyClass()) ce qui est a mon avis un
moyen assez performant pour instancier n objets et pouvoir y accéder
rapidement ensuite.
Franchement, ce genre de problème deperformances ne devrait pas t'embêter
v.push_back( MyClass() ); // l'objet temporaire est alloué
sur
Aïe, l'objet temporaire est détruit. Il faut donc que je ruse pour
que le destructeur ne libère pas des ressources que la copie pourrait
utiliser.
Ce que tu ne sembles pas avoir compris, c'est que pour pouvoir être stockés
Ce que je veux c'est dynamiquement allouer de la mémoire (un tableau
de n objets, malloc( sizeof(MyClass)*n ) ) et instancier un objet à
chaque emplacement (new (&vec[i]) MyClass()) ce qui est a mon avis un
moyen assez performant pour instancier n objets et pouvoir y accéder
rapidement ensuite.
Franchement, ce genre de problème deperformances ne devrait pas t'embêter
v.push_back( MyClass() ); // l'objet temporaire est alloué
sur
Aïe, l'objet temporaire est détruit. Il faut donc que je ruse pour
que le destructeur ne libère pas des ressources que la copie pourrait
utiliser.
Ce que tu ne sembles pas avoir compris, c'est que pour pouvoir être stockés
Ce que je veux c'est dynamiquement allouer de la mémoire (un tableau
de n objets, malloc( sizeof(MyClass)*n ) ) et instancier un objet à
chaque emplacement (new (&vec[i]) MyClass()) ce qui est a mon avis un
moyen assez performant pour instancier n objets et pouvoir y accéder
rapidement ensuite.
Franchement, ce genre de problème deperformances ne devrait pas t'embêter
v.push_back( MyClass() ); // l'objet temporaire est alloué
sur
Aïe, l'objet temporaire est détruit. Il faut donc que je ruse pour
que le destructeur ne libère pas des ressources que la copie pourrait
utiliser.
Ce que tu ne sembles pas avoir compris, c'est que pour pouvoir être stockés
Est-il possible d'utiliser std::vector de telle sorte que les appels à
resize construisent chaque objet plutôt que d'utiliser un copy
constructor ?
L'idée est d'avoir un fonctionnement similaire à celui du code suivant
mais en évitant la copie de l'objet et le gâchis de mémoire :
vector<MyClass> vec;
vec.reserve(20);
for( int i=0; i<10; ++i )
{
vec.push_back( *(new MyClass()) );
}
A défaut, quelle est la façon propre de faire un
// construire l'objet
MyClass *tmp = new MyClass();
// le placer dans le tableau
vec.push_back( *tmp );
// limérer la mémoire sans appeler le destructeur
free( tmp );
Je veux bien fournir mon propre copy constructor et lui faire créer un
nouvel objet de toutes pièces, mais cela est d'une part détourner son
vrai objectif et d'autre part cela risque d'interférer avec les vraies
copies d'objet.
Est-il possible d'utiliser std::vector de telle sorte que les appels à
resize construisent chaque objet plutôt que d'utiliser un copy
constructor ?
L'idée est d'avoir un fonctionnement similaire à celui du code suivant
mais en évitant la copie de l'objet et le gâchis de mémoire :
vector<MyClass> vec;
vec.reserve(20);
for( int i=0; i<10; ++i )
{
vec.push_back( *(new MyClass()) );
}
A défaut, quelle est la façon propre de faire un
// construire l'objet
MyClass *tmp = new MyClass();
// le placer dans le tableau
vec.push_back( *tmp );
// limérer la mémoire sans appeler le destructeur
free( tmp );
Je veux bien fournir mon propre copy constructor et lui faire créer un
nouvel objet de toutes pièces, mais cela est d'une part détourner son
vrai objectif et d'autre part cela risque d'interférer avec les vraies
copies d'objet.
Est-il possible d'utiliser std::vector de telle sorte que les appels à
resize construisent chaque objet plutôt que d'utiliser un copy
constructor ?
L'idée est d'avoir un fonctionnement similaire à celui du code suivant
mais en évitant la copie de l'objet et le gâchis de mémoire :
vector<MyClass> vec;
vec.reserve(20);
for( int i=0; i<10; ++i )
{
vec.push_back( *(new MyClass()) );
}
A défaut, quelle est la façon propre de faire un
// construire l'objet
MyClass *tmp = new MyClass();
// le placer dans le tableau
vec.push_back( *tmp );
// limérer la mémoire sans appeler le destructeur
free( tmp );
Je veux bien fournir mon propre copy constructor et lui faire créer un
nouvel objet de toutes pièces, mais cela est d'une part détourner son
vrai objectif et d'autre part cela risque d'interférer avec les vraies
copies d'objet.
Franchement, ce genre de problème deperformances ne devrait pas
t'embêter pour l'instant, surtout si tu es sous Windows donc sans
contraintes temps réel fortes. "Early otpimisation is the root of all
evil". Commences par faire une solution :
1) Correcte.
2) Facilement compréhensible.
3) Maintenable.
... et seulement ensuite préoccupes toi de performances, si des
mesures avec u profiler révèlent que c'est nécessaire.
Ce que tu ne sembles pas avoir compris, c'est que pour pouvoir être
stockés dans un vector, tes objets doivent être copiables ce qui n'est
pas le cas actuellement à cause de ton handle ou autre référence
système. Ce que tu dois faire, c'est donc écrire un constructeur par
copie qui donne une sémantique de copie correcte à ton objet.
Franchement, ce genre de problème deperformances ne devrait pas
t'embêter pour l'instant, surtout si tu es sous Windows donc sans
contraintes temps réel fortes. "Early otpimisation is the root of all
evil". Commences par faire une solution :
1) Correcte.
2) Facilement compréhensible.
3) Maintenable.
... et seulement ensuite préoccupes toi de performances, si des
mesures avec u profiler révèlent que c'est nécessaire.
Ce que tu ne sembles pas avoir compris, c'est que pour pouvoir être
stockés dans un vector, tes objets doivent être copiables ce qui n'est
pas le cas actuellement à cause de ton handle ou autre référence
système. Ce que tu dois faire, c'est donc écrire un constructeur par
copie qui donne une sémantique de copie correcte à ton objet.
Franchement, ce genre de problème deperformances ne devrait pas
t'embêter pour l'instant, surtout si tu es sous Windows donc sans
contraintes temps réel fortes. "Early otpimisation is the root of all
evil". Commences par faire une solution :
1) Correcte.
2) Facilement compréhensible.
3) Maintenable.
... et seulement ensuite préoccupes toi de performances, si des
mesures avec u profiler révèlent que c'est nécessaire.
Ce que tu ne sembles pas avoir compris, c'est que pour pouvoir être
stockés dans un vector, tes objets doivent être copiables ce qui n'est
pas le cas actuellement à cause de ton handle ou autre référence
système. Ce que tu dois faire, c'est donc écrire un constructeur par
copie qui donne une sémantique de copie correcte à ton objet.
Bon on va dire qu'on va oublier les bêtises que j'ai pu raconter, surtout
sur la fin.
Bon on va dire qu'on va oublier les bêtises que j'ai pu raconter, surtout
sur la fin.
Bon on va dire qu'on va oublier les bêtises que j'ai pu raconter, surtout
sur la fin.
Pour résumer, d'après les post précédents, tu veux :
1 - Que les instances des tes objets soient contigües en mémoire.
2 - Supporter des objets non copiables.
3 - Pouvoir agrandir/réduire le tableau dynamiquement.
La STL impose que les objets soient copiables ce qui implique
déplaçables. Ton problème avec ça c'est que le constructeur de copie
peut coûter cher s'il doit copier beaucoup de données, alors qu'il
pourrait juste en transférer la responsabilité.
Pour moi c'est un faux problème, car
soit l'objet ne coûte pas cher à copier, soit il coûte cher et il
suffit d'en manipuler un (smart-)pointeur pour que ça ne coûte pas
cher.
En fait, il faudrait un constructeur qui prenne l'objet à
déplacer en paramètre, le copie/déplace et laisse l'objet déplacé dans
un état indéterminé mais destructible. On va appeler ça un "move
constructor" :-). Que nenni, on peut toujours l'implémenter soi-même :
C'est superTM. Ca impose juste d'avoir un move constructor pour
toutes les classes que tu veux utiliser avec ton conteneur (c'est à
dire que toutes les classes dont elles dérivent ou qu'elles englobent
directement ont un move constructor), ce qui en pratique est une
contrainte hyper-forte. Dans le style maintenable on a fait mieux, et
il reste à prouver qu'on a gagner quelque chose à faire ça.
Pour résumer, chez moi j'ai un gain d'environ 40% en faveur du move
constructor. Pas mal (et pas hyper suprenant non plus sinon il n'y
aurait pas de "proposal" en sa faveur), mais honnêtement pas suffisant
pour que ça vaille la peine de se prendre la tête à moins d'écrire un
bibliothèque de calcul numérique. De plus le test est hautement
criticable: il ne mesure pas le coût des réallocations, et travaille
sur des ensembles d'éléments assez énormes pour que le gain ait un
sens quelconque. Mais si vous avez mieux à proposer...
Pour résumer, d'après les post précédents, tu veux :
1 - Que les instances des tes objets soient contigües en mémoire.
2 - Supporter des objets non copiables.
3 - Pouvoir agrandir/réduire le tableau dynamiquement.
La STL impose que les objets soient copiables ce qui implique
déplaçables. Ton problème avec ça c'est que le constructeur de copie
peut coûter cher s'il doit copier beaucoup de données, alors qu'il
pourrait juste en transférer la responsabilité.
Pour moi c'est un faux problème, car
soit l'objet ne coûte pas cher à copier, soit il coûte cher et il
suffit d'en manipuler un (smart-)pointeur pour que ça ne coûte pas
cher.
En fait, il faudrait un constructeur qui prenne l'objet à
déplacer en paramètre, le copie/déplace et laisse l'objet déplacé dans
un état indéterminé mais destructible. On va appeler ça un "move
constructor" :-). Que nenni, on peut toujours l'implémenter soi-même :
C'est superTM. Ca impose juste d'avoir un move constructor pour
toutes les classes que tu veux utiliser avec ton conteneur (c'est à
dire que toutes les classes dont elles dérivent ou qu'elles englobent
directement ont un move constructor), ce qui en pratique est une
contrainte hyper-forte. Dans le style maintenable on a fait mieux, et
il reste à prouver qu'on a gagner quelque chose à faire ça.
Pour résumer, chez moi j'ai un gain d'environ 40% en faveur du move
constructor. Pas mal (et pas hyper suprenant non plus sinon il n'y
aurait pas de "proposal" en sa faveur), mais honnêtement pas suffisant
pour que ça vaille la peine de se prendre la tête à moins d'écrire un
bibliothèque de calcul numérique. De plus le test est hautement
criticable: il ne mesure pas le coût des réallocations, et travaille
sur des ensembles d'éléments assez énormes pour que le gain ait un
sens quelconque. Mais si vous avez mieux à proposer...
Pour résumer, d'après les post précédents, tu veux :
1 - Que les instances des tes objets soient contigües en mémoire.
2 - Supporter des objets non copiables.
3 - Pouvoir agrandir/réduire le tableau dynamiquement.
La STL impose que les objets soient copiables ce qui implique
déplaçables. Ton problème avec ça c'est que le constructeur de copie
peut coûter cher s'il doit copier beaucoup de données, alors qu'il
pourrait juste en transférer la responsabilité.
Pour moi c'est un faux problème, car
soit l'objet ne coûte pas cher à copier, soit il coûte cher et il
suffit d'en manipuler un (smart-)pointeur pour que ça ne coûte pas
cher.
En fait, il faudrait un constructeur qui prenne l'objet à
déplacer en paramètre, le copie/déplace et laisse l'objet déplacé dans
un état indéterminé mais destructible. On va appeler ça un "move
constructor" :-). Que nenni, on peut toujours l'implémenter soi-même :
C'est superTM. Ca impose juste d'avoir un move constructor pour
toutes les classes que tu veux utiliser avec ton conteneur (c'est à
dire que toutes les classes dont elles dérivent ou qu'elles englobent
directement ont un move constructor), ce qui en pratique est une
contrainte hyper-forte. Dans le style maintenable on a fait mieux, et
il reste à prouver qu'on a gagner quelque chose à faire ça.
Pour résumer, chez moi j'ai un gain d'environ 40% en faveur du move
constructor. Pas mal (et pas hyper suprenant non plus sinon il n'y
aurait pas de "proposal" en sa faveur), mais honnêtement pas suffisant
pour que ça vaille la peine de se prendre la tête à moins d'écrire un
bibliothèque de calcul numérique. De plus le test est hautement
criticable: il ne mesure pas le coût des réallocations, et travaille
sur des ensembles d'éléments assez énormes pour que le gain ait un
sens quelconque. Mais si vous avez mieux à proposer...
Il doit sûrement y avoir des raisons à cela, mais je trouve ça horr ible
et au risque de me faire incendier, un realloc() bien utilisé est quand
même vachement pratique.
Il doit sûrement y avoir des raisons à cela, mais je trouve ça horr ible
et au risque de me faire incendier, un realloc() bien utilisé est quand
même vachement pratique.
Il doit sûrement y avoir des raisons à cela, mais je trouve ça horr ible
et au risque de me faire incendier, un realloc() bien utilisé est quand
même vachement pratique.
Pour résumer, d'après les post précédents, tu veux :
1 - Que les instances des tes objets soient contigües en mémoire.
2 - Supporter des objets non copiables.
3 - Pouvoir agrandir/réduire le tableau dynamiquement.
Exactement.
Pour résumer, d'après les post précédents, tu veux :
1 - Que les instances des tes objets soient contigües en mémoire.
2 - Supporter des objets non copiables.
3 - Pouvoir agrandir/réduire le tableau dynamiquement.
Exactement.
Pour résumer, d'après les post précédents, tu veux :
1 - Que les instances des tes objets soient contigües en mémoire.
2 - Supporter des objets non copiables.
3 - Pouvoir agrandir/réduire le tableau dynamiquement.
Exactement.