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

initialisation par new d'une dommée membre static

8 réponses
Avatar
Marc G
Une organisation du type suivant m'arrangerait bien

Fichier hpp
class X
{
X() {...}
...
static X* ptr;
static X& ref;
};

Fichier cpp

X* X::ptr=new X();
X& X::ref=(*ptr);

blablabla...

Même si c'est pas très élégant, ça m'arrange beaucoup...et je suis très
pressé :-(((
La donnée membre static est utilisée pour stocker temporairement des
résultats d'opérations qui portent sur des types dérivés de X...
Est-ce que cette façon de faire présente un risque ?
Merci de vos conseils
Marc

8 réponses

Avatar
IR
Marc G wrote:

Une organisation du type suivant m'arrangerait bien

Fichier hpp
class X
{
X() {...}
...
static X* ptr;
static X& ref;
};

Fichier cpp

X* X::ptr=new X();
X& X::ref=(*ptr);

blablabla...

Même si c'est pas très élégant, ça m'arrange beaucoup...et je suis
très pressé :-(((
La donnée membre static est utilisée pour stocker temporairement
des résultats d'opérations qui portent sur des types dérivés de
X... Est-ce que cette façon de faire présente un risque ?
Merci de vos conseils


Un problème évident : aucun delete n'est réalisé!!


Je suppose que tu as de bonnes raisons pour préférer un

X* X::ptr = new X();

plutôt que

X X::ptr = X();

(bien que je voie difficilement lesquelles...)



Pourquoi ne pas utiliser un auto_ptr? Au moins le destructeur de X
sera appellé:

class X
{
X() {...}
...
static std::auto_ptr<X> ptr;
static X& ref;
};

//Fichier cpp

std::auto_ptr<X> X::ptr(new X());
X& X::ref=(*ptr);


Cheers,
--
IR

Avatar
Fabien LE LEZ
On Mon, 15 Jan 2007 19:28:11 +0100 (CET), IR :

Un problème évident : aucun delete n'est réalisé!!


Ce qui n'est pas gênant ici, si le destructeur ne fait rien de
passionnant.

Avatar
IR
Fabien LE LEZ wrote:

On Mon, 15 Jan 2007 19:28:11 +0100 (CET), IR :

Un problème évident : aucun delete n'est réalisé!!


Ce qui n'est pas gênant ici, si le destructeur ne fait rien de
passionnant.


La seule chose qui me gêne dans ta phrase, c'est le "si"... ;-)

(comment ça je suis maniaque? :p)

Cheers,
--
IR


Avatar
Fabien LE LEZ
On Mon, 15 Jan 2007 21:27:02 +0100 (CET), IR :

Ce qui n'est pas gênant ici, si le destructeur ne fait rien de
passionnant.


La seule chose qui me gêne dans ta phrase, c'est le "si"... ;-)


Disons que d'une manière générale, un singleton est rarement détruit.


Avatar
James Kanze
IR wrote:
Marc G wrote:

Une organisation du type suivant m'arrangerait bien

Fichier hpp
class X
{
X() {...}
...
static X* ptr;
static X& ref;
};

Fichier cpp

X* X::ptr=new X();
X& X::ref=(*ptr);

blablabla...

Même si c'est pas très élégant, ça m'arrange beaucoup...



Ça serait intéressant de savoir pourquoi. Qu'on ait un pointeur,
ou une référence (selon le cas), ça se conçoit, mais pourquoi en
faut-il les deux, pour la même chose.

et je suis
très pressé :-(((
La donnée membre static est utilisée pour stocker temporairement
des résultats d'opérations qui portent sur des types dérivés de
X...



Là, je suis encore moins. Pour stocker temporairement des
résultats des opérations, j'ai une tendance à préférer les
temporaires.

Est-ce que cette façon de faire présente un risque ?
Merci de vos conseils


Un problème évident : aucun delete n'est réalisé!!


Ce qui n'est pas forcément un problème. Je conçois mes
singletons à ne jamais avoir un delete exprès.

Je suppose que tu as de bonnes raisons pour préférer un

X* X::ptr = new X();

plutôt que

X X::ptr = X();

(bien que je voie difficilement lesquelles...)


Parce que le nom est ptr, ce qui suggère un pointeur:-).

Sérieusement, la raison principale, c'est d'éviter que le
destructeur soit jamais appelé. Sinon, parfois, on le fait pour
avoir du polymorphisme, où le type réel n'est connu qu'à
l'exécution (d'après une variable de l'environement, par
exemple).

Pourquoi ne pas utiliser un auto_ptr? Au moins le destructeur de X
sera appellé:


Justement. Dans ce genre d'utilisation, c'est en général mieux
de ne pas appeler le destructeur.

--
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
Fabien LE LEZ wrote:
On Mon, 15 Jan 2007 21:27:02 +0100 (CET), IR :

Ce qui n'est pas gênant ici, si le destructeur ne fait rien de
passionnant.


La seule chose qui me gêne dans ta phrase, c'est le "si"... ;-)


Disons que d'une manière générale, un singleton est rarement détr uit.


N'est-ce pas ? En fait, en générale, il vaut mieux que non ;
l'idiome même assure l'ordre de construction, mais la seule
façon à être sûr qu'il n'est pas détruit trop tôt, c'est de ne
pas le détruire du tout.

Il faut se poser la question : pourquoi un destructeur ? C'est
un outil formidable pour assurer l'exécution du code de
nettoyage, lorsqu'on quitte une portée. Mais cette justification
ne s'applique qu'aux objets avec une portée locale. C'est aussi
un « nom » conventionnel pour la fonction qui termine la durée
de vie d'un objet, dans le cas des objets qui ont des durées de
vie précises, c-à-d qui sont créés et detruits en fonction des
évenemments (entrées, etc.) externes. Sinon, on est souvent
amené à s'en servir pous la gestion de la mémoire. C'est une
utilisation un peu artificielle, en ce qu'il en existe de bien
meilleurs solutions, comme le collecteur de Boehm, mais pour
diverses raisons, on y s'y trouve souvent obligé.

Et ensuite ? Aucune de ces raisons ne s'appliquent ici, et je
n'en vois pas d'autres.

--
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
Marc G
Ma classe X n'a pas grand chose comme donnée membre...
Avec le constructeur par défaut, ce sera juste un pointeur NULL (et il me
semble que quand le programme se termine, tout est libéré, même sans appel
des destructeurs). Donc pas de pb de ce côté là !
Mais par la suite X peut pointer vers des "gros" objets, via le...
polymorphysme.
C'est pour ça qu'il me faut une référence vers le contenu d'un pointeur et
non vers un objet X...
Et malheureusement, je ne peux pas initialiser la référence si ptr==NULL

si dans le fichier cppp, j'ai
X* X::ptr=new X();
X& X::ref=(*ptr);

je peux utiliser ptr pour stocker "temporairement" certains objets.
Bon, bien sûr, il faut être prudent. Mais la rapidité de mon code est
importante.
Et je sais quand je le fais (dans certaines méthodes qui exigent un retour
par référence et j'utilise ptr et ref directement dans ces méthodes).
Je récupère le resultat toujours immédiatement après.
Et quand je veux libérer la mémoire prise par un gros objet, rien de
m'empêche de l'effacer puis réécrire ptr=new X();
Voilà,
mais je voudrais être sûr que ptr est toujours initialiser.
Je maîtrise (ou comprends ?) pas bien l'ordre et le processus
d'initialisation des unités..
Mais merci de vos réponses. J'ai l'impression (?) que je peux le faire.
Marc
Avatar
James Kanze
Marc G wrote:
Ma classe X n'a pas grand chose comme donnée membre...
Avec le constructeur par défaut, ce sera juste un pointeur NULL (et il me
semble que quand le programme se termine, tout est libéré, même san s appel
des destructeurs). Donc pas de pb de ce côté là !
Mais par la suite X peut pointer vers des "gros" objets, via le...
polymorphysme.


Pour voir si j'ai bien compris : c'est un peu comme un
singleton, mais le type réel peut varier en cours d'exécution.

C'est pour ça qu'il me faut une référence vers le contenu d'un poin teur et
non vers un objet X...


Une fois initialisée, tu ne peux pas changer le référé. Donc, tu
ne peux pas en changer le type. (En C++, un objet donné ne
change jamais de type.)

Et malheureusement, je ne peux pas initialiser la référence si ptr= =NULL

si dans le fichier cppp, j'ai
X* X::ptr=new X();
X& X::ref=(*ptr);

je peux utiliser ptr pour stocker "temporairement" certains objets.
Bon, bien sûr, il faut être prudent. Mais la rapidité de mon code e st
importante.
Et je sais quand je le fais (dans certaines méthodes qui exigent un ret our
par référence et j'utilise ptr et ref directement dans ces méthodes ).
Je récupère le resultat toujours immédiatement après.
Et quand je veux libérer la mémoire prise par un gros objet, rien de
m'empêche de l'effacer puis réécrire ptr=new X();


D'abord, un new ne libère jamais de la mémoire (au moins d'avoir
un constructeur vraiment bizarre). Et dans ce cas-ci,
heureusement, parce que la réfèrence continue à désigner l'objet
initial.

Je ne suis pas sûr d'avoir bien compris, mais je me démande si
tu n'es pas en train de faire quelque chose du genre :

X&
operator+( X const& a, X const& b )
{
// ...
return ref ;
}

pour essayer d'éviter la copie de la valeur du retour. Si oui,
je te signale que ce n'est vraiment pas une bonne idée, et qu'il
existe d'autres solutions, bien plus adaptées, et sans risques.

mais je voudrais être sûr que ptr est toujours initialiser.
Je maîtrise (ou comprends ?) pas bien l'ordre et le processus
d'initialisation des unités..
Mais merci de vos réponses. J'ai l'impression (?) que je peux le faire.


Moi, j'ai l'impression que tu es bien partie pour te casser la
gueule.

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