OVH Cloud OVH Cloud

CComPtr en paramètre de fonction...

1 réponse
Avatar
michael.delva
Bonjour =E0 tous,

Pourquoi est ce que le code suivant ne fonctionne pas?
Est-ce qu'il existe une autre mani=E8re de passer des CComPtr en
param=E8tre de fonction?

class toto
{
private:
CComPtr<IGraphBuilder> pGraph;
public:
void SetGraph(CComPtr<IGraphBuilder> graph)
{
pGraph =3D graph;
}
};

class foo
{
private:
toto t;

CComPtr<IGraphBuilder> pGraph;

// blablabla...
public:
foo()
{
t.SetGraph(pGraph);
}
};

Apr=E8s l'appel de t.SetGraph(pGraph), un appel =E0
IGraphBuilder::Release() est d=E9clench=E9, ce qui fait que mon objet
pGraph est r=E9initialis=E9...

Comment je dois passer =E7a?

1) Passer le pointeur brut:

void toto::SetGraph(IGraphBuilder * graph)
{
pGraph =3D graph;
}

foo::foo()
{
t=2ESetGraph(pGraph);
}

2) Passer par un pointeur de CComPtr?

void toto::SetGraph(CComPtr<IGraphBuilder> * ppgraph)
{
pGraph =3D *ppgraph;
}

foo::foo()
{
t=2ESetGraph(&pGraph);
}

J'avoue =EAtre un peu perdu avec le comptage des r=E9f=E9rences...

Est-ce que quelqu'un peut =E9clairer ma lanterne?

Merci d'avance

1 réponse

Avatar
Cyrille Szymanski
wrote in news:1151008342.406793.295330
@b68g2000cwa.googlegroups.com:

Bonjour, je n'en sais pas beaucoup, mais je dirai que c'est un faux
problème :

class toto
{
private:
CComPtr<IGraphBuilder> pGraph;
public:
void SetGraph(CComPtr<IGraphBuilder> graph)
{
pGraph = graph;
}
};



Après l'appel de t.SetGraph(pGraph), un appel à
IGraphBuilder::Release() est déclenché, ce qui fait que mon objet
pGraph est réinitialisé...



CComPtr est un "pointeur intelligent" c'est à dire qu'il se charge
d'encapsuler la libération de la ressource associée dès qu'il est lui-
même détruit.

Le problème avec ton code c'est qu'en écrivant des choses genre "void
SetGraph(CComPtr<IGraphBuilder> graph)" et "pGraph = graph" tu fais du
passage par valeur, un autre objet CComPtr temporaire est créé puis
détruit (d'où l'appel à Release).

La rustine à appliquer est donc de faire un passage par référence.

Est-ce qu'il existe une autre manière de passer des CComPtr en
paramètre de fonction?



Mais la question reste : pourquoi vouloir passer un CComPtr ? Cet objet
ne te sert qu'à encapsuler une ressource dont tu dois t'assurer qu'elle
sera détruite correctement. Deux cas :

Soit tu laisses la gestion de la mémoire à la méthode appelante, dans ce
cas la classe Toto n'a pas à détruire l'objet et un pointeur fait bien
son boulot.

Soit tu veux déléguer la gestion de la mémoire à la classe Toto (le Graph
est créé par la méthode appelante, puis attaché à une instance de la
classe Toto et tu veux que le graphe soit détruit quand Toto est
détruite) dans ce cas c'est à Toto de créer le CComPtr.

J'espère avoir été clair et ne pas avoir dit trop de bêtises.

--
Cyrille Szymanski