[Résolu] Gestion de la mémoire.

K-lo
[Résolu] Gestion de la mémoire.

Bon ça va sembler être une question bête mais je commence à me mélanger les méninges (ah ces bonnes vieilles expressions... :D) !
Comment est gérer la mémoire avec C++ dans ce cas :

1 objet A qui créait 1 objet B.
Le main créer A et le supprime (utilisation de new et delete)
Question que devient B ?

A::A(){
 B *b = new B();
 /*   /!\   pas de delete b;  /!\ */
}

main(){
A *a = new A();
delete a;
}

Et est-ce que si B est une interface, cela se passe de la même manière ?

Biensur placer un "delete b;" dans le code de la classe A serait nettement plus de la programmation mais ma question est plus de bien comprendre le comportement de la mémoire.

fredericmazue

Quote:
Question que devient B ?

Fuite mémoire :)

Quote:
Et est-ce que si B est une interface, cela se passe de la même manière ?

Ben, une interface ça n'existe pas en C++. Tu as du mal t'exprimer là.

Quote:
Biensur placer un "delete b;" dans le code de la classe A serait nettement plus de la programmation

Pas sur, pas sûr :)
J'ai bien compris ton propos. Mais je te fais quand même une proposition:
 std::auto_ptr<B> p_B; 

comme membre de la classe.
Maintenant attention!.
Je sais que tu codes avec Qt en ce moment. Tu as posé la question pour A et B, j'ai répondu pour A et B. MAIS, si A et B sont des widgets tels que B est enfant de A, alors il n'y a pas de fuite mémoire. QT s'occupe de le gérer :)
C'était peut être ça que tu voulais dire par interface ? des widgets ?
K-lo

Non là c'était pas pour QT mais c'est asser sympathique de savoir qu'il gere tot bien comme il faut :D

Je parlais de MFC (oui je sais mais moi aussi jlé aime pas vraiment), avec ce qui est appeler "Interface"
Mais bon cette question m'est venu en écrivant mon topic et n'a donc pas grande importance... De plus, les méthodes Release() doivent en théorie libérer les mémoires...

std::auto_ptr<B> p_B; ça j'y pense jamais :oops:

Donc et bien merci pour m'avoir répondu a cette question plutot basic.

fredericmazue

Quote:
Interface" ... De plus, les méthodes Release()
Ah il s'agit d'interfaces COM.
Dans ce cas auto_ptr ne convient pas bien sûr puisqu'il ne vas pas appeler Release. Mais rien de plus facile que de t'écrire un pointeur intelligent dans l'esprit de auto_ptr pour interfaces COM une fois pour toutes.
Sinon dans le cas général auto_ptr, auot_ptr est une pratique vraiment à recommander.

PS: Ce message est le 1000eme que je poste sur ce forum. Spécialement pour toi ;) :)

A bientôt :)

K-lo

J'ai ce petit bout de code :

wstring *nom;
wstring compare;
if( wstring(*nom).erase(0, nom.end()-3 ) == compare){
   ...
}

Je ne sais pas comment ce comporte la mémoire dans ce cas là
si cela va se comporter comporter comme un test sur un int ou non...

fredericmazue

Je dois dire que je ne comprends pas tout dans la question :shock:

Quel est le rapport entre le comportement de la mémoire et un test sur un int ?
De plus ton code ne compile pas. Il est même assez loin de compiler je pense. (*)

Mais sur le fond, tu coupes une chaîne et tu compares à une autre, donc le test consiste entre une comparaison de chaîne. Et comme l'opérateur == renvoie un booléen c'est sur un bool que "se comporte le test"

(*) A voir ton code je me demande
- si tu veux utiliser le méthode compare de string ou pas ?
- si tu n'as pas oublié que end doit être un itérateur ?

K-lo

effectivement ça compile pas a cause du nom.end()-3 car justement c'est un iterateur (non j'ai pas oublier c'était de l'assimilation :?) au lieu de faire nom.length()-3 et ça ça compile (compare doit être réservée :? mais ma question n'était pas sur ce sujet.

Ce que je voulais savoir si cette manière de créer une chaine était ou non à déconseillé :
wstring(*nom).erase(0, nom.length()-3) histoire qu'on est pas comme pour les pointeurs des fuites de mémoires ou je ne sais quel autre problème.

Pour ce qui est de la comparaison c'était juste pour un exmple... :(

fredericmazue

Quote:
aire nom.length()-3 et ça ça compile

ok :)
Quote:
histoire qu'on est pas comme pour les pointeurs des fuites de mémoires

Normalement tu n'as pas de fuite
wstring(*nom) est un objet temporaire qui existe seulement le temps du test dans le if et qui est détruit juste après
K-lo

Oki merci pour la confirmation et désolé mes questions pas toujours très clair :?

fredericmazue

Pas de problème :)

K-lo

Voilà je souhaite éviter le problème récurrent de la STL (et pas que de la STL :D) : la copie d'objet
En effet, j'ai une classe R qui doit avoir une donnée membre de B (non modifiable) qui sera passé en argument au constructeur de R.

Or j'ai lu :

Quote:
- Il est rare de recevoir une référence non const en paramètre
- Un paramètre pointeur constant représente toujours un tableau
- Il ne faut pas utiliser les références comme attribut d'un objet.

Class InformationsBase //la classe B
{
 std::string info1;
 //...
};

Class Recept//La classe R
{
   private :
   B _b* //voir si c'est la bonne solution...
   public :  
   InformationsSupp(const B& b){
      //comment lier _b et b
   }
}

Comment lier le paramètre avec la donnée membre sans avoir à faire une copie d'objet et donc le plus propre possible ?
fredericmazue

Quote:
Or j'ai lu :

Ou ça :?: :!:
Quote:
Il est rare de recevoir une référence non const en paramètre

Si seulement...
Quote:
Un paramètre pointeur constant représente toujours un tableau

N'importe quoi...
Quote:
Il ne faut pas utiliser les références comme attribut d'un objet.

Et pourquoi pas ?

Quote:
Comment lier le paramètre avec la donnée membre sans avoir à faire une copie d'objet et donc le plus propre possible ?

Si l'instance d'InformationsBase est sur le tas, un auto_ptr est toujours une solution sympa. Voir Recept1 ci-dessous. Mais attention Recept1 ne va que si elle n'est pas copiée à son tour :!: (A cause de l'auto_ptr)
Dans les cas plus complexes, utiliser par exemple boot:shared_ptr (que je n'utilise moi même jamais)
Si l'instance de InformationsBase est sur la pile, pas de problème avec les références membres. Voir ci dessous Recept2. Mais attention l'objet référencé ne doit pas être détruit par une sortie de portée évidemment.

#include <iostream>
#include <memory>
#include <string>

using namespace std;


class InformationsBase  
{
private:
 std::string info1; 
public: 
	InformationsBase(string s) : info1(s) {}
	~InformationsBase() {cout << info1 << " destruction" << endl;}
	void hello() const {cout << info1 << endl;}
}; 

class Recept1
{ 
private : 
   auto_ptr<const InformationsBase> inner_b;
public :
	Recept1(const InformationsBase* const b) : inner_b(b) {}
	void hello() {inner_b->hello();}
};

class Recept2
{ 
private : 
   const InformationsBase& inner_b;
public :
	Recept2(const InformationsBase& b) : inner_b(b) {}
	~Recept2() {cout << "detenteur reference: destruction" << endl;}
	void hello() {inner_b.hello();}
};

int main(int argc, char* argv[])
{
	// 1ere possibilité
	Recept1 r1(new InformationsBase("ib pointeur"));
	r1.hello();

	// 2eme possibilité
	InformationsBase ib("ib reference");
	Recept2 r2(ib);
	r2.hello();

	return 0;
}

Mais plus que tout bien se demander si ça vaut la peine de se prendre le chou pour éviter une copie d'objet

K-lo

Quote:
Mais plus que tout bien se demander si ça vaut la peine de se prendre le chou pour éviter une copie d'objet

Et bien heu... :oops: c'était pour être avisé sur la meilleur solution.

Merci Fred (héhé j'espérais bien voir un auto_ptr pour une copie d'objet :D)
L'url à bannir :
http://www.prados.fr/Langage/CPP/ref/ref.pdf

fredericmazue

Quote:
L'url à bannir :

Ben, je ne suis pas d'accord.
D'abord Philippe Prados, c'est un bon, ensuite c'est un copain, et enfin c'est un auteur dans Programmez! (moins ces derniers temps il est vrai, mais ça ne lui enlève rien)
Dans le document que tu cites, il dit que les références peuvent être pénalisantes parce que fois initialisées tu ne peux pas les ré-affecter, ce qui est vrai. Mais il ne dit pas qu'il ne faut pas avoir références comme membres de classes.
Bon c'est sûr que si tu dois réaffecter la référence ne vas pas, et l'auto_ptr va bien sous réserve (j'insiste) que l'objet dont il est membre ne soit pas copié lui même. Tu peux aussi avoir un simple pointeur si la classe qui le détient n'est pas responsable de la gestion de la durée de vie de l'objet pointé.
K-lo

Quote:
D'abord Philippe Prados, c'est un bon, ensuite c'est un copain, et enfin c'est un auteur dans Programmez!

Je n'ai rien contre cette personne ça serait trop prétentieux de ma part. D'ailleurs j'ai imprimé son document et surtout je me serais pas attardé sur le sujet.
Bon certes le mot bannir :oops: est peut être trop fort et c'était surtout au vu des 3 rmq... mais les phrases que j'ai cité au dessus sont bien dans ce document.
D'ailleurs reprenons les remarques :

Quote:
Le compilateur ne génère pas l’opérateur d’affectation. Il ne faut donc pas utiliser les références comme attribut d’un objet.
au vu des problèmes que l'on peut rencontrer ça semble être plus un conseil... car on peut vite tomber dans les travers de la réaffectation...

Quote:
Il est rare de recevoir une référence non const en paramètre

Quote:
Si seulement...
je suppose que c'est plus dans le sens de la programmation "propre" (exemple avec les vector "balancé" en paramètre comme tu m'as fait corrigé / puis corrigé toi même sur un autre topic ), non?

Quote:
Un paramètre pointeur constant représente toujours un tableau

Quote:
N'importe quoi...
Même au vu du comportement ?

************************************************************

Quote:
Tu peux aussi avoir un simple pointeur si la classe qui le détient n'est pas responsable de la gestion de la durée de vie de l'objet pointé.

Justement c'est la solution la mieux adapté.