 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Jean-Marc Bourguet Guest
|
Posted: Sat Aug 23, 2003 5:42 pm Post subject: Re: déplacement d'objets |
|
|
"Cyrille "cns" Szymanski" <cns2 (AT) cns (DOT) invalid> writes:
| Quote: | Pour résumer mes derniers posts, sont apparus deux problèmes liés au
déplacement d'objets :
1_ std::vector<> (et la STL en général) a besoin d'objets copiables
pour pouvoir fonctionner. Ok, je comprends tout à fait pourquoi,
bien que je ne sois pas encore persuadé qu'il n'y ait pas d'autre
solution, toute aussi simple qui n'impose pas cette limitation.
|
Vu que la notion de déplacement d'objet n'existe pas en C++, ou tu
copies ton objet dans le conteneur, ou tu le construis directement à
sa place définitive (ce qui est exclus pour std::vector<> -- du moins
il faudrait toujours pouvoir copier -- mais serait envisageable pour
les autres dont std::deque<>).
Donc pour ajouter un élément tu aurais une fonction à laquelle tu
passerais une fonction qui construit ton élément en place ou bien tu
limites ces fonctions à être des constructeurs et tu passes les
arguments du constructeurs. C'aurait été envisagable mais j'ai pas
analysé comment ça se serait intégré dans les principes de base de la
STL.
| Quote: | 2_ pour déplacer un objet il faut le rendre copiable.
|
Plus exactement il n'y a pas de notion de déplacement d'objet. Le
plus proche est la copie suivie de la destruction de la source. On
peut concevoir une notion de copie qui ne soit pas équivalente à ça.
En fait le problème principal de l'introduction d'une notion de copie
est d'en fournir une définition cohérente des contraintes, des effets
et des avantages (je n'en vois qu'un -- la performance -- et bien
souvent il est surestimé).
| Quote: | Là ça me choque qu'on pense comme ça et je ne vois pas ce qui
empêche un objet d'être déplacé.
|
Donne une bonne définition de déplacement de l'objet alors? Est-ce
que les références existantes continues à être valide? Si oui,
comment tu fais gérer ça? Si non, ce n'est pas un déplacement mais
bien la construction d'un nouvel objet accompagnée de la destruction
de l'ancien, qu'est-ce qu'apporte donc ce nouveau concept?
| Quote: | Je m'étonne que le C++ n'ait pas fait abstraction de ça alors qu'une
des règles d'or est que les pointeurs c'est moche.
|
Je ne connais pas une application non triviale qui n'utilise pas de
l'allocation dynamique plus ou moins controlée (parfois à la mode
FORTRAN: un tableau et des indices).
| Quote: | Ne pas pouvoir déplacer un objet c'est une incitation à utiliser
new.
|
J'attends une définition précise de ce qu'est déplacer un objet avant
de répondre.
| Quote: | Dans le fond, un objet c'est juste une zone mémoire qui contient les
valeurs de ses membres et sur laquelle on appelle des fonctions.
Alors ça devrait très bien résister à un realloc() ça.
|
Non. Deux objets peuvent avoir très bien des membres parfaitement
identiques et être différents, ce qui résiste très mal à realloc.
| Quote: | Je vous soumets le code suivant pour revue. Il implémente un tableau
dynamique dans lequel je peux instancier des objets non copiables.
allocate( nb ) : s'assure que le tableau contient nb objets (il détruit
ceux en trop et instancie ceux qui manquent).
Avec ça je peux faire mon tableau de ressources sans me casser la tête.
template <class Obj
struct cnsArray
{
Obj *m_ptr;
|
pourquoi est-ce public?
| Quote: | unsigned int m_nb;
|
idem, pourquoi unsigned (mais ça risque d'être un autre débat).
| Quote: | cnsArray()
{
m_ptr = NULL;
m_nb = 0;
}
|
Pourquoi ne pas utiliser la liste d'initialisation?
| Quote: | ~cnsArray()
{
if( m_ptr!=0 )
{
for( unsigned int i=m_nb; i>0; --i )
{
m_ptr[i-1].~Obj();
}
m_ptr = 0;
m_nb = 0;
}
}
|
Et la mémoire pointée par m_ptr, elle est libérée quand?
Pourquoi assigner des valeurs à m_ptr et m_nb qui ne sont pas
vivantes?
| Quote: | int allocate( unsigned int nb )
{
FATAL( nb!=0 );
|
C'est quoi fatal?
| Quote: | int ret=-1;
if( nb<m_nb )
{
// détruire les objets supprimés
for( unsigned int i=m_nb; i>nb; --i )
{
m_ptr[i-1].~Obj();
}
}
Obj *m_ptr_tmp = (Obj*)realloc( m_ptr, nb*sizeof(Obj) );
|
Théoriquement, ce n'est valable que pour des POD. En pratique, j'ai
un tas de classes qui ne supporte pas ce comportement de sauvage et il
y a des techniques d'implémentation de l'héritage multiple qui ne le
supporte pas.
| Quote: | if( m_ptr_tmp!=0 )
{
m_ptr = m_ptr_tmp;
// initialiser les nouveaux objets
for( unsigned int i=m_nb; i
{
new (&m_ptr[i]) Obj();
}
m_nb = nb;
ret = 0;
}
else
{
// la taille n'a pas pu être modifiée
ret = -1;
}
return ret;
}
};
|
Si tu veux retourner une valeur, pourquoi pas un bool?
--
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
|
|
| Back to top |
|
 |
Cyrille cns Szymanski Guest
|
Posted: Sat Aug 23, 2003 7:43 pm Post subject: Re: déplacement d'objets |
|
|
| Quote: | Plus exactement il n'y a pas de notion de déplacement d'objet.
|
Je m'en doutais un peu. L'autre question est : est-il nécessaire de
déplacer des objets ?
Pourtant un vector<> doit bien déplacer des objets au sens où il lui arrive
de devoir s'agrandir et donc il doit déménager ses données.
| Quote: | Donne une bonne définition de déplacement de l'objet alors? Est-ce
que les références existantes continues à être valide? Si oui,
comment tu fais gérer ça? Si non, ce n'est pas un déplacement mais
bien la construction d'un nouvel objet accompagnée de la destruction
de l'ancien, qu'est-ce qu'apporte donc ce nouveau concept?
|
Evidemment utiliser une ancienne référence sur un objet qui a été déplacé
est une mauvaise idée. Il faudrait mettre en place un système pour tracer
les objets, ce qui performances mises à part semble intéressant. Après tout
le grabage collector a bien été adopté par pléthore de gens. Mais là n'est
pas mon propos.
Déplacer un objet pour moi c'est une opération de transfert de
responsabilité : il n'y a aucun appel de fonction de la classe (l'opération
est transparente de son point de vue), l'ancien objet n'est plus "valide"
et sa destruction se limite à la libération de la mémoire, le nouvel objet
doit être égal à l'ancien (le même mais à un autre endroit dans la
mémoire), aucun constructeur n'est appelé. C'est comme si on pouvait faire
un "&T = nouvelle_adresse;"
Ça apporterait la possibilité de ballader un objet non copiable (dans des
conteneurs par exemple). C'est par exemple éviter d'écrire du code pour
compter les références d'une ressource utilisée dans une classe dont il
n'existe que des instances distinctes (au sens où elles n'ont pas été
créées par copy constructor).
| Quote: | unsigned int m_nb;
idem, pourquoi unsigned (mais ça risque d'être un autre débat).
|
A priori à la question "combien" je réponds par un nombre positif.
| Quote: | cnsArray()
{
m_ptr = NULL;
m_nb = 0;
}
Pourquoi ne pas utiliser la liste d'initialisation?
|
C'est le "cnsArray() : m_ptr(NULL), m_nb(0)" ? Qu'apporte cette
construction ?
| Quote: | Obj *m_ptr_tmp = (Obj*)realloc( m_ptr, nb*sizeof(Obj) );
Théoriquement, ce n'est valable que pour des POD. En pratique, j'ai
un tas de classes qui ne supporte pas ce comportement de sauvage et il
y a des techniques d'implémentation de l'héritage multiple qui ne le
supporte pas.
|
Là en tant que néophyte je suis curieux de voir un exemple.
Merci pour votre temps,
--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/
|
|
| Back to top |
|
 |
Cyrille cns Szymanski Guest
|
Posted: Sat Aug 23, 2003 7:55 pm Post subject: Re: déplacement d'objets |
|
|
| Quote: | Il y a une solution que tu n'aimes pas. C'est tout. (Les pointeurs,
intelligents ou pas)
|
C'est vrai que mettre des pointeurs dans le vector résoudra le problème de
la copie mais posera celui de la destruction (cf thread "liste d'auto_ptr")
| Quote: | Dans le fond, un objet c'est juste une zone mémoire qui contient les
valeurs de ses membres et sur laquelle on appelle des fonctions.
Alors ça devrait très bien résister à un realloc() ça.
Je crois que tu ne connais/comprends pas bien realloc.
|
Ok j'ai mélangé deux choses :
* Soit je voulais dire "résister à un memmove()
* Soit je faisais référence au fait que (dans mon cas) je modifie la
taille du tableau d'objets grâce à realloc() et que parfois realloc() doit
copier les données.
| Quote: | Je vous soumets le code suivant pour revue. Il implémente un tableau
dynamique dans lequel je peux instancier des objets non copiables.
[...]
Tu devrais lire les discussions sur comp.lang.c++.moderated.
|
Tu parles de la NTL ?
--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/
|
|
| Back to top |
|
 |
Cyrille Karmann Guest
|
Posted: Sat Aug 23, 2003 10:03 pm Post subject: Re: déplacement d'objets |
|
|
"Cyrille "cns" Szymanski" <cns2 (AT) cns (DOT) invalid> disait...
| Quote: | Plus exactement il n'y a pas de notion de déplacement d'objet.
Déplacer un objet pour moi c'est une opération de transfert de
responsabilité :
|
Encore une fois, il y a des pointeurs intelligents pour transférer les
responsabilités.
| Quote: | Ça apporterait la possibilité de ballader un objet non copiable (dans des
conteneurs par exemple). C'est par exemple éviter d'écrire du code pour
compter les références d'une ressource utilisée dans une classe dont il
n'existe que des instances distinctes (au sens où elles n'ont pas été
créées par copy constructor).
|
Quand je vois ton code, je me demande "comment on utilise ça?" Bref,
j'ai un peu de mal à voir comment tu écris les fonctions pour
insérer/retirer des éléments et pour y accéder si les objets ne sont pas
copiables. A moins que m_ptr soit public pour faire ça auquel cas je
suis franchement dubitatif.
| Quote: | cnsArray()
{
m_ptr = NULL;
m_nb = 0;
}
Pourquoi ne pas utiliser la liste d'initialisation?
C'est le "cnsArray() : m_ptr(NULL), m_nb(0)" ? Qu'apporte cette
construction ?
|
De manière générale, ça apporte de bonnes habitudes (comme c'est
obligatoire pour initialiser une référence ou un objet qui n'a pas de
constructeur sans argument, autant le faire pour tout le monde. Et puis
je sais pas vous, mais moi j'aime pas avoir des pointeurs non
initialisés qui se baladent...).
Accessoirement, c'est aussi censé être plus performant, je crois. Même
si ici ce n'est pas critique.
--
Cyrille
|
|
| Back to top |
|
 |
Alain Naigeon Guest
|
Posted: Sat Aug 23, 2003 10:54 pm Post subject: Re: déplacement d'objets |
|
|
"Cyrille "cns" Szymanski" <cns2 (AT) cns (DOT) invalid> a écrit dans le message news:
Xns93E0DD00C6286cns2cnsinvalid (AT) 193 (DOT) 252.19.141...
| Quote: | Déplacer un objet pour moi c'est une opération de transfert de
responsabilité : il n'y a aucun appel de fonction de la classe
(l'opération
est transparente de son point de vue), l'ancien objet n'est plus "valide"
et sa destruction se limite à la libération de la mémoire, le nouvel objet
doit être égal à l'ancien (le même mais à un autre endroit dans la
mémoire), aucun constructeur n'est appelé.
|
Hé, ce n'est pas pour rien qu'il existe des constructeurs de copie.
Un objet peut en comporter d'autres (qui à leur tour, etc) et ne
peut connaître la façon dont il faut les copier - c'est chacun d'eux
qui sait comment il faut faire (= leur constructeur de copie).
La copie est, en général, une opération hautement non triviale !
--
Français *==> "Musique renaissance" <==* English
midi - facsimiles - ligatures - mensuration
http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/
Alain Naigeon - [email]anaigeon (AT) free (DOT) fr[/email] - Strasbourg, France
|
|
| Back to top |
|
 |
Loïc Joly Guest
|
Posted: Sun Aug 24, 2003 6:46 am Post subject: Re: déplacement d'objets |
|
|
Cyrille "cns" Szymanski wrote:
| Quote: | cnsArray()
{
m_ptr = NULL;
m_nb = 0;
}
Pourquoi ne pas utiliser la liste d'initialisation?
C'est le "cnsArray() : m_ptr(NULL), m_nb(0)" ? Qu'apporte cette
construction ?
|
Toi qui est si friand d'optimisation et de suppression de copies
inutiles, voila ca que ferait ta construction si m_ptr et m_nb étaient
des classes et non des types de base :
- Créer m_ptr et m_nb avec leur constructeur par défaut.
- Utiliser l'opérateur dégalité pour mettre dedans une autre valeur (qui
a probablement été elle même construite par un constructeur avec arguments).
Alors que la deuxième écriture fait
- Créer m_ptr et m_nb avec le constructeur qui va bien.
--
Loïc
|
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Sun Aug 24, 2003 12:41 pm Post subject: Re: déplacement d'objets |
|
|
On 24 Aug 2003 12:32:36 GMT, "Cyrille "cns" Szymanski"
<cns2 (AT) cns (DOT) invalid> wrote:
| Quote: | (POD sans pointeurs, mais non copiables
|
C'est contradictoire, non ?
|
|
| Back to top |
|
 |
Cyrille cns Szymanski Guest
|
Posted: Sun Aug 24, 2003 12:49 pm Post subject: Re: déplacement d'objets |
|
|
| Quote: | (POD sans pointeurs, mais non copiables
C'est contradictoire, non ?
|
Avec des HANDLE ?
--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/
|
|
| Back to top |
|
 |
Jean-Marc Bourguet Guest
|
Posted: Sun Aug 24, 2003 2:28 pm Post subject: Re: déplacement d'objets |
|
|
"Cyrille "cns" Szymanski" <cns2 (AT) cns (DOT) invalid> writes:
| Quote: | Déplacer un objet pour moi c'est une opération de transfert de
responsabilité :
Encore une fois, il y a des pointeurs intelligents pour transférer les
responsabilités.
Et cela rajoute un niveau d'indirection.
Oh crap, allez j'abandonne.
Tout ce que je voulais c'était étant donné des gentils objets (POD sans
pointeurs, mais non copiables)
|
Un POD est copiable par définition. Comme les pointeurs, les handles
sont copiables. Comme les pointeurs, la difficulté est de savoir qui
doit les libérer. Comme pour les pointeurs il n'y a pas de politique
qui convienne à tous les cas. Comme pour les pointeurs, une fois
définie une politique, tu peux définir une classe qui aide à
l'enforcer. Comme pour les pointeurs, je n'ai pas encore rencontré de
cas où une politique où une notion de transfert est fondamentale: le
transfert se fait entre un nombre suffisemment limité d'endroits qui
sont suffisemment sous contrôle pour que la difficulté à enforcer ça
automatiquement (c'est possible, voir auto_ptr, mais voir les
discussions sur les subtilités d'implémentation) et l'impossibilité de
se servir des conteneurs de la bibliothèque standard soient des
problèmes (autrement dit ça ne vaut pas la peine de se casser la tête
pour ne pas utiliser le pointeur ou le handle directement).
| Quote: | les mettre dans un tableau. Apparemment ça pose trop de problèmes,
je vais me contenter de les rendre copiables, ce sera toujours plus
efficace que de rajouter un niveau d'indirection.
|
Tu peux implémenter quelque chose du genre, par rapport à
l'utilisation nue tu n'as qu'un coût à la construction, aux copies et
à la destruction.
typedef int Handle;
class SharedHandle
{
public:
explicit SharedHandle(Handle);
SharedHandle(SharedHandle const&);
SharedHandle& operator=(SharedHandle const&);
~SharedHandle();
...
private:
Handle myHandle;
static std::map<Handle, int> ourCount;
};
SharedHandle::SharedHandle(Handle h)
: myHandle(h)
{
++ourCount[myHandle];
}
SharedHandle::SharedHandle(SharedHandle const& other)
: myHandle(other.myHandle)
{
++ourCount[myHandle];
}
SharedHandle& operator=(SharedHandle const& other)
{
Handle old = myHandle;
myHandle = other.myHandle;
++ourCount[myHande];
std::map<Handle, int>::iterator it = ourCound.find(old);
assert(it != ourCount.end());
if (--(*it).second == 0) {
ourCount.erase[it];
FreeHandle(old);
}
}
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
|
|
| Back to top |
|
 |
Jean-Marc Bourguet Guest
|
Posted: Sun Aug 24, 2003 2:44 pm Post subject: Re: déplacement d'objets |
|
|
"Cyrille "cns" Szymanski" <cns2 (AT) cns (DOT) invalid> writes:
| Quote: | Plus exactement il n'y a pas de notion de déplacement d'objet.
Je m'en doutais un peu. L'autre question est : est-il nécessaire de
déplacer des objets ?
Pourtant un vector<> doit bien déplacer des objets au sens où il lui
arrive de devoir s'agrandir et donc il doit déménager ses données.
|
Il les copie et détruit l'original. Tout comme realloc, à part que
les notions de copie et de destruction utilisée sont différentes.
| Quote: | Donne une bonne définition de déplacement de l'objet alors?
[...]
il n'y a aucun appel de fonction de la classe
|
Tellement peu général que je doute que ce soit une "bonne" définition
de déplacement. L'idée de transfert de responsabilité est plus
intéressante, mais comme je l'ai écrit par ailleurs, je la trouve
aussi d'application peu générale (ou bien le transfert se fait à
l'intérieur d'un module bien contrôlé et utiliser des pointeurs bruts
pose peu de problèmes ou bien partager la responsabilité est une
extension raisonnable même si ce n'est pas utilisé dans le système
actuel, parfois même le transfert à été spécifié à cause d'un manque
de connaissance des techniques permettant de partager la
responsabilité).
| Quote: | cnsArray()
{
m_ptr = NULL;
m_nb = 0;
}
Pourquoi ne pas utiliser la liste d'initialisation?
C'est le "cnsArray() : m_ptr(NULL), m_nb(0)" ? Qu'apporte cette
construction ?
|
Construire directement les membres avec leur valeur finale.
| Quote: | Obj *m_ptr_tmp = (Obj*)realloc( m_ptr, nb*sizeof(Obj) );
Théoriquement, ce n'est valable que pour des POD. En pratique,
j'ai un tas de classes qui ne supporte pas ce comportement de
sauvage et il y a des techniques d'implémentation de l'héritage
multiple qui ne le supporte pas.
Là en tant que néophyte je suis curieux de voir un exemple.
|
Dès que ton objet maintient quelque par un pointeur vers lui-même, ça
pose un problème. Le compilateur peut le faire pour implémenter
l'héritage multiple virtuel par exemple, ou l'objet peut s'être
enregistré quelque part, contenir un weak_ptr, gérer des "fils" qui
ont des pointeurs vers lui-même, ...
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
|
|
| Back to top |
|
 |
Cyrille cns Szymanski Guest
|
Posted: Sun Aug 24, 2003 4:20 pm Post subject: Re: déplacement d'objets |
|
|
| Quote: | Théoriquement, ce n'est valable que pour des POD. En pratique,
j'ai un tas de classes qui ne supporte pas ce comportement de
sauvage et il y a des techniques d'implémentation de l'héritage
multiple qui ne le supporte pas.
Là en tant que néophyte je suis curieux de voir un exemple.
Dès que ton objet maintient quelque par un pointeur vers lui-même, ça
pose un problème. Le compilateur peut le faire pour implémenter
l'héritage multiple virtuel par exemple, ou l'objet peut s'être
enregistré quelque part, contenir un weak_ptr, gérer des "fils" qui
ont des pointeurs vers lui-même, ...
|
Oui j'ai vu qu'il y avait des implémentations de std::string qui n'étaient
pas copiables.
Merci pour ces informations.
--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|