j'ai un petit probleme avec la gestion d'une mémoire allouée
dynamiquement dans une fonction
vect &
vect::operator+(const vect &v) const
{
vect *p = new vect;
for(unsigned int i=0; i<x.size(); i ++)
{
*(p->x[i]) = (*x[i] + *(v.x[i]));
}
return *p;
}
imaginons que 'vect' soit un objet comprenant un vector 'x' qui lui
même contient un ensemble de pointeurs sur des objets dont la nature
nous importe peut (nous savons qu'ils ont un opérateur '+' défini)
je veux définir l'opérateur '+' pour mon objet 'vect', qui devra
additionner tous les objets pointés par son vector 'x' avec ceux
pointés par un autre vect.
pour celà j'alloue dynamiquement un espace mémoire de type 'vect', puis
je boucle sur le tableau, en espérant que cette ligne a l'intérieur de
la boucle soit correcte...
puis je retourne une référence sur mon objet dynamique avec 'return
*p;'
maintenant imaginons que j'utilise cet opérateur dans une autre
fonction :
{
vect a,b,c;
a = b + c;
}
comment a la sortie de la fonction libérer la mémoire alouée ??
j'ai un petit probleme avec la gestion d'une mémoire allouée dynamiquement dans une fonction
vect & vect::operator+(const vect &v) const
En général, on déclare l'opérateur + en dehors de la classe. Ceci pour des raisons de symétrie (sinon, le premier terme doit être un vect, et le deuxième un truc castable en vect, ce qui rompt la symétrie de l'addition) (et on défini operator+ à partir de operator+=).
Ensuite, l'opérateur devrait retourner un objet, et non pas une référence ou un pointeur. Ca peut poser des problèmes de performance, puisque du coup l'objet va être copié, mais ce problème peut être réduit :
- Certains compilateur implémentent la RVO (return value optimisation), qui leur permet d'éviter une copie dans ce genre de cas.
Certains, ou prèsque tous ?
Mais ça a des limites. Si j'écris : vect v( a + b ) ; ça marche, mais dans : v = a + b ; c'est moins sûr. Il y aurait au moins une copie.
- Il est possible de retourner non pas un vecteur mais un objet qui se souvient de l'opération effectuée, et ne va réellement additionner que quand on va accèder au contenu, tout en faisant cette gymnastique à la compilation (voir par exemple blitz::tiny_vector sur www.oonumerics.org, se munir d'une aspirine)
C'est la solution consacrée. En théorie, il faut faire vachement attention à la durée de vie des objets, mais dans la pratique, ça marche pas trop mal, parce que les objets intermédiaires qui dépendent des autres objets sont tous des temporaires.
- Certains travaillent à founir au C++ une sémantique de déplacement en plus de la sémantique de copie omniprésente actuellement. Si ton programme peut attendre quelques années... ;)
- Dans certains cas, une fonction void add (vect const &A, vect const &B, vect &Result) peut aider, mais l'écriture n'est vraiment pas belle.
On pourrait aussi utiliser COW, surtout si le programme n'est pas multi-threadé.
-- James Kanze GABI Software 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
Loïc Joly <loic.actarus.joly@wanadoo.fr> wrote in message
news:<cbckct$aol$1@news-reader3.wanadoo.fr>...
Nicolas Aunai wrote:
j'ai un petit probleme avec la gestion d'une mémoire allouée
dynamiquement dans une fonction
vect &
vect::operator+(const vect &v) const
En général, on déclare l'opérateur + en dehors de la classe. Ceci pour
des raisons de symétrie (sinon, le premier terme doit être un vect, et
le deuxième un truc castable en vect, ce qui rompt la symétrie de
l'addition) (et on défini operator+ à partir de operator+=).
Ensuite, l'opérateur devrait retourner un objet, et non pas une
référence ou un pointeur. Ca peut poser des problèmes de performance,
puisque du coup l'objet va être copié, mais ce problème peut être
réduit :
- Certains compilateur implémentent la RVO (return value
optimisation), qui leur permet d'éviter une copie dans ce genre de
cas.
Certains, ou prèsque tous ?
Mais ça a des limites. Si j'écris :
vect v( a + b ) ;
ça marche, mais dans :
v = a + b ;
c'est moins sûr. Il y aurait au moins une copie.
- Il est possible de retourner non pas un vecteur mais un objet qui se
souvient de l'opération effectuée, et ne va réellement additionner que
quand on va accèder au contenu, tout en faisant cette gymnastique à la
compilation (voir par exemple blitz::tiny_vector sur
www.oonumerics.org, se munir d'une aspirine)
C'est la solution consacrée. En théorie, il faut faire vachement
attention à la durée de vie des objets, mais dans la pratique, ça marche
pas trop mal, parce que les objets intermédiaires qui dépendent des
autres objets sont tous des temporaires.
- Certains travaillent à founir au C++ une sémantique de déplacement
en plus de la sémantique de copie omniprésente actuellement. Si ton
programme peut attendre quelques années... ;)
- Dans certains cas, une fonction void add (vect const &A, vect const
&B, vect &Result) peut aider, mais l'écriture n'est vraiment pas
belle.
On pourrait aussi utiliser COW, surtout si le programme n'est pas
multi-threadé.
--
James Kanze GABI Software
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
j'ai un petit probleme avec la gestion d'une mémoire allouée dynamiquement dans une fonction
vect & vect::operator+(const vect &v) const
En général, on déclare l'opérateur + en dehors de la classe. Ceci pour des raisons de symétrie (sinon, le premier terme doit être un vect, et le deuxième un truc castable en vect, ce qui rompt la symétrie de l'addition) (et on défini operator+ à partir de operator+=).
Ensuite, l'opérateur devrait retourner un objet, et non pas une référence ou un pointeur. Ca peut poser des problèmes de performance, puisque du coup l'objet va être copié, mais ce problème peut être réduit :
- Certains compilateur implémentent la RVO (return value optimisation), qui leur permet d'éviter une copie dans ce genre de cas.
Certains, ou prèsque tous ?
Mais ça a des limites. Si j'écris : vect v( a + b ) ; ça marche, mais dans : v = a + b ; c'est moins sûr. Il y aurait au moins une copie.
- Il est possible de retourner non pas un vecteur mais un objet qui se souvient de l'opération effectuée, et ne va réellement additionner que quand on va accèder au contenu, tout en faisant cette gymnastique à la compilation (voir par exemple blitz::tiny_vector sur www.oonumerics.org, se munir d'une aspirine)
C'est la solution consacrée. En théorie, il faut faire vachement attention à la durée de vie des objets, mais dans la pratique, ça marche pas trop mal, parce que les objets intermédiaires qui dépendent des autres objets sont tous des temporaires.
- Certains travaillent à founir au C++ une sémantique de déplacement en plus de la sémantique de copie omniprésente actuellement. Si ton programme peut attendre quelques années... ;)
- Dans certains cas, une fonction void add (vect const &A, vect const &B, vect &Result) peut aider, mais l'écriture n'est vraiment pas belle.
On pourrait aussi utiliser COW, surtout si le programme n'est pas multi-threadé.
-- James Kanze GABI Software 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
Nomak
Le 23/06/2004 à 20:07:20, Nicolas Aunai a écrit:
salut,
j'ai un petit probleme avec la gestion d'une mémoire allouée dynamiquement dans une fonction
vect & vect::operator+(const vect &v) const { vect *p = new vect; for(unsigned int i=0; i<x.size(); i ++) { *(p->x[i]) = (*x[i] + *(v.x[i])); } return *p; }
imaginons que 'vect' soit un objet comprenant un vector 'x' qui lui même contient un ensemble de pointeurs sur des objets dont la nature nous importe peut (nous savons qu'ils ont un opérateur '+' défini)
je veux définir l'opérateur '+' pour mon objet 'vect', qui devra additionner tous les objets pointés par son vector 'x' avec ceux pointés par un autre vect.
pour celà j'alloue dynamiquement un espace mémoire de type 'vect', puis je boucle sur le tableau, en espérant que cette ligne a l'intérieur de la boucle soit correcte...
puis je retourne une référence sur mon objet dynamique avec 'return *p;'
maintenant imaginons que j'utilise cet opérateur dans une autre fonction :
{
vect a,b,c;
a = b + c;
}
comment a la sortie de la fonction libérer la mémoire alouée ??
merci
Alloue ton vecteur sur la pile:
vect & vect::operator+(const vect &v) const { // si on ne peut pas additionner partiellemnt assert(x.size() == v.x.size());
// le constructeur par défaut alloue suffisemment de mémoire? // c'est pas vect res(x.size()); ? vect res;
// res.x = x + v.x for (unsigned i = 0; i < x.size(); i++) *res.x[i] = *x[i] + *v.x[i];
// copie de la pile vers l'espace automatique // le compilo devrait optimiser ça return res; }
Tu peux aussi faire:
vect & vect::operator+(const vect &v) const { // si on ne peut pas additionner partiellemnt assert(x.size() == v.x.size());
vect res(*this);
// res.x += v.x for (unsigned i = 0; i < x.size(); i++) *res.x[i] += *v.x[i];
// copie de la pile vers l'espace automatique // le compilo devrait optimiser ça return res; }
On suppose que vect::~vect libère come il faut la mémoire, et il n'y a pas de fuites.
-- Nomak
Le 23/06/2004 à 20:07:20, Nicolas Aunai <nicolas.aunai@free.fr> a
écrit:
salut,
j'ai un petit probleme avec la gestion d'une mémoire allouée
dynamiquement dans une fonction
vect &
vect::operator+(const vect &v) const
{
vect *p = new vect;
for(unsigned int i=0; i<x.size(); i ++)
{
*(p->x[i]) = (*x[i] + *(v.x[i]));
}
return *p;
}
imaginons que 'vect' soit un objet comprenant un vector 'x' qui lui
même contient un ensemble de pointeurs sur des objets dont la nature
nous importe peut (nous savons qu'ils ont un opérateur '+' défini)
je veux définir l'opérateur '+' pour mon objet 'vect', qui devra
additionner tous les objets pointés par son vector 'x' avec ceux
pointés par un autre vect.
pour celà j'alloue dynamiquement un espace mémoire de type 'vect', puis
je boucle sur le tableau, en espérant que cette ligne a l'intérieur de
la boucle soit correcte...
puis je retourne une référence sur mon objet dynamique avec 'return
*p;'
maintenant imaginons que j'utilise cet opérateur dans une autre
fonction :
{
vect a,b,c;
a = b + c;
}
comment a la sortie de la fonction libérer la mémoire alouée ??
merci
Alloue ton vecteur sur la pile:
vect &
vect::operator+(const vect &v) const
{
// si on ne peut pas additionner partiellemnt
assert(x.size() == v.x.size());
// le constructeur par défaut alloue suffisemment de mémoire?
// c'est pas vect res(x.size()); ?
vect res;
// res.x = x + v.x
for (unsigned i = 0; i < x.size(); i++)
*res.x[i] = *x[i] + *v.x[i];
// copie de la pile vers l'espace automatique
// le compilo devrait optimiser ça
return res;
}
Tu peux aussi faire:
vect &
vect::operator+(const vect &v) const
{
// si on ne peut pas additionner partiellemnt
assert(x.size() == v.x.size());
vect res(*this);
// res.x += v.x
for (unsigned i = 0; i < x.size(); i++)
*res.x[i] += *v.x[i];
// copie de la pile vers l'espace automatique
// le compilo devrait optimiser ça
return res;
}
On suppose que vect::~vect libère come il faut la mémoire, et il n'y a
pas de fuites.
j'ai un petit probleme avec la gestion d'une mémoire allouée dynamiquement dans une fonction
vect & vect::operator+(const vect &v) const { vect *p = new vect; for(unsigned int i=0; i<x.size(); i ++) { *(p->x[i]) = (*x[i] + *(v.x[i])); } return *p; }
imaginons que 'vect' soit un objet comprenant un vector 'x' qui lui même contient un ensemble de pointeurs sur des objets dont la nature nous importe peut (nous savons qu'ils ont un opérateur '+' défini)
je veux définir l'opérateur '+' pour mon objet 'vect', qui devra additionner tous les objets pointés par son vector 'x' avec ceux pointés par un autre vect.
pour celà j'alloue dynamiquement un espace mémoire de type 'vect', puis je boucle sur le tableau, en espérant que cette ligne a l'intérieur de la boucle soit correcte...
puis je retourne une référence sur mon objet dynamique avec 'return *p;'
maintenant imaginons que j'utilise cet opérateur dans une autre fonction :
{
vect a,b,c;
a = b + c;
}
comment a la sortie de la fonction libérer la mémoire alouée ??
merci
Alloue ton vecteur sur la pile:
vect & vect::operator+(const vect &v) const { // si on ne peut pas additionner partiellemnt assert(x.size() == v.x.size());
// le constructeur par défaut alloue suffisemment de mémoire? // c'est pas vect res(x.size()); ? vect res;
// res.x = x + v.x for (unsigned i = 0; i < x.size(); i++) *res.x[i] = *x[i] + *v.x[i];
// copie de la pile vers l'espace automatique // le compilo devrait optimiser ça return res; }
Tu peux aussi faire:
vect & vect::operator+(const vect &v) const { // si on ne peut pas additionner partiellemnt assert(x.size() == v.x.size());
vect res(*this);
// res.x += v.x for (unsigned i = 0; i < x.size(); i++) *res.x[i] += *v.x[i];
// copie de la pile vers l'espace automatique // le compilo devrait optimiser ça return res; }
On suppose que vect::~vect libère come il faut la mémoire, et il n'y a pas de fuites.
-- Nomak
tib.motuelle
Nomak wrote in message news:<ot0cgwb7edmn.juz96zxhxob5$...
Le 23/06/2004 à 20:07:20, Nicolas Aunai a écrit:
j'ai un petit probleme avec la gestion d'une mémoire allouée dynamiquement dans une fonction vect & vect::operator+(const vect &v) const { vect *p = new vect; for(unsigned int i=0; i<x.size(); i ++) { *(p->x[i]) = (*x[i] + *(v.x[i])); } return *p;
}
[...]
maintenant imaginons que j'utilise cet opérateur dans une autre fonction : { vect a,b,c; a = b + c; }
comment a la sortie de la fonction libérer la mémoire alouée ??
Alloue ton vecteur sur la pile:
Oui mais si tu ne changes pas le type de retour (l'opérateur doit retourner un nouvel objet, pas une référence), tu as juste transformé la fuite mémoire en comportement indéfini (qui devrait rapidement se traduire par un plantage à l'execution).
[snip première version]
vect & vect::operator+(const vect &v) const { // si on ne peut pas additionner partiellemnt assert(x.size() == v.x.size());
vect res(*this);
// res.x += v.x for (unsigned i = 0; i < x.size(); i++) *res.x[i] += *v.x[i];
// copie de la pile vers l'espace automatique // le compilo devrait optimiser ça return res; } Ici "res" sort de la portée et est détruit. La référence retournée est
invalide.
En changeant le type de retour de l'opérateur en: vect vect::operator+(const vect &v) const
Tu retournes maintenant une copie de res (qui peut être optimisée), et les choses rentrent dans l'ordre.
Bertrand.
Nomak <no.email@invalid.domain.fr> wrote in message news:<ot0cgwb7edmn.juz96zxhxob5$.dlg@40tude.net>...
Le 23/06/2004 à 20:07:20, Nicolas Aunai <nicolas.aunai@free.fr> a
écrit:
j'ai un petit probleme avec la gestion d'une mémoire allouée
dynamiquement dans une fonction
vect &
vect::operator+(const vect &v) const
{
vect *p = new vect;
for(unsigned int i=0; i<x.size(); i ++)
{
*(p->x[i]) = (*x[i] + *(v.x[i]));
}
return *p;
}
[...]
maintenant imaginons que j'utilise cet opérateur dans une autre
fonction :
{
vect a,b,c;
a = b + c;
}
comment a la sortie de la fonction libérer la mémoire alouée ??
Alloue ton vecteur sur la pile:
Oui mais si tu ne changes pas le type de retour (l'opérateur doit
retourner un nouvel objet, pas une référence), tu as juste transformé
la fuite mémoire en comportement indéfini (qui devrait rapidement se
traduire par un plantage à l'execution).
[snip première version]
vect &
vect::operator+(const vect &v) const
{
// si on ne peut pas additionner partiellemnt
assert(x.size() == v.x.size());
vect res(*this);
// res.x += v.x
for (unsigned i = 0; i < x.size(); i++)
*res.x[i] += *v.x[i];
// copie de la pile vers l'espace automatique
// le compilo devrait optimiser ça
return res;
}
Ici "res" sort de la portée et est détruit. La référence retournée est
invalide.
En changeant le type de retour de l'opérateur en:
vect
vect::operator+(const vect &v) const
Tu retournes maintenant une copie de res (qui peut être optimisée), et
les choses rentrent dans l'ordre.
Nomak wrote in message news:<ot0cgwb7edmn.juz96zxhxob5$...
Le 23/06/2004 à 20:07:20, Nicolas Aunai a écrit:
j'ai un petit probleme avec la gestion d'une mémoire allouée dynamiquement dans une fonction vect & vect::operator+(const vect &v) const { vect *p = new vect; for(unsigned int i=0; i<x.size(); i ++) { *(p->x[i]) = (*x[i] + *(v.x[i])); } return *p;
}
[...]
maintenant imaginons que j'utilise cet opérateur dans une autre fonction : { vect a,b,c; a = b + c; }
comment a la sortie de la fonction libérer la mémoire alouée ??
Alloue ton vecteur sur la pile:
Oui mais si tu ne changes pas le type de retour (l'opérateur doit retourner un nouvel objet, pas une référence), tu as juste transformé la fuite mémoire en comportement indéfini (qui devrait rapidement se traduire par un plantage à l'execution).
[snip première version]
vect & vect::operator+(const vect &v) const { // si on ne peut pas additionner partiellemnt assert(x.size() == v.x.size());
vect res(*this);
// res.x += v.x for (unsigned i = 0; i < x.size(); i++) *res.x[i] += *v.x[i];
// copie de la pile vers l'espace automatique // le compilo devrait optimiser ça return res; } Ici "res" sort de la portée et est détruit. La référence retournée est
invalide.
En changeant le type de retour de l'opérateur en: vect vect::operator+(const vect &v) const
Tu retournes maintenant une copie de res (qui peut être optimisée), et les choses rentrent dans l'ordre.
Bertrand.
Nomak
Le 24/06/2004 à 16:27:24, Bertrand Motuelle a écrit:
Alloue ton vecteur sur la pile:
Oui mais si tu ne changes pas le type de retour (l'opérateur doit retourner un nouvel objet, pas une référence), tu as juste transformé la fuite mémoire en comportement indéfini (qui devrait rapidement se traduire par un plantage à l'execution).
[snip première version]
vect & vect::operator+(const vect &v) const { // si on ne peut pas additionner partiellemnt assert(x.size() == v.x.size());
vect res(*this);
// res.x += v.x for (unsigned i = 0; i < x.size(); i++) *res.x[i] += *v.x[i];
// copie de la pile vers l'espace automatique // le compilo devrait optimiser ça return res; } Ici "res" sort de la portée et est détruit. La référence retournée est
invalide.
En changeant le type de retour de l'opérateur en: vect vect::operator+(const vect &v) const
Tu retournes maintenant une copie de res (qui peut être optimisée), et les choses rentrent dans l'ordre.
Tout à fait, désolé
-- Nomak
Le 24/06/2004 à 16:27:24, Bertrand Motuelle <tib.motuelle@laposte.net>
a écrit:
Alloue ton vecteur sur la pile:
Oui mais si tu ne changes pas le type de retour (l'opérateur doit
retourner un nouvel objet, pas une référence), tu as juste transformé
la fuite mémoire en comportement indéfini (qui devrait rapidement se
traduire par un plantage à l'execution).
[snip première version]
vect &
vect::operator+(const vect &v) const
{
// si on ne peut pas additionner partiellemnt
assert(x.size() == v.x.size());
vect res(*this);
// res.x += v.x
for (unsigned i = 0; i < x.size(); i++)
*res.x[i] += *v.x[i];
// copie de la pile vers l'espace automatique
// le compilo devrait optimiser ça
return res;
}
Ici "res" sort de la portée et est détruit. La référence retournée est
invalide.
En changeant le type de retour de l'opérateur en:
vect
vect::operator+(const vect &v) const
Tu retournes maintenant une copie de res (qui peut être optimisée), et
les choses rentrent dans l'ordre.
Le 24/06/2004 à 16:27:24, Bertrand Motuelle a écrit:
Alloue ton vecteur sur la pile:
Oui mais si tu ne changes pas le type de retour (l'opérateur doit retourner un nouvel objet, pas une référence), tu as juste transformé la fuite mémoire en comportement indéfini (qui devrait rapidement se traduire par un plantage à l'execution).
[snip première version]
vect & vect::operator+(const vect &v) const { // si on ne peut pas additionner partiellemnt assert(x.size() == v.x.size());
vect res(*this);
// res.x += v.x for (unsigned i = 0; i < x.size(); i++) *res.x[i] += *v.x[i];
// copie de la pile vers l'espace automatique // le compilo devrait optimiser ça return res; } Ici "res" sort de la portée et est détruit. La référence retournée est
invalide.
En changeant le type de retour de l'opérateur en: vect vect::operator+(const vect &v) const
Tu retournes maintenant une copie de res (qui peut être optimisée), et les choses rentrent dans l'ordre.
Tout à fait, désolé
-- Nomak
Mathieu Roger
salut,
j'ai un petit probleme avec la gestion d'une mémoire allouée dynamiquement dans une fonction
vect & vect::operator+(const vect &v) const { vect *p = new vect; for(unsigned int i=0; i<x.size(); i ++) { *(p->x[i]) = (*x[i] + *(v.x[i])); } return *p; }
imaginons que 'vect' soit un objet comprenant un vector 'x' qui lui même contient un ensemble de pointeurs sur des objets dont la nature nous importe peut (nous savons qu'ils ont un opérateur '+' défini)
je veux définir l'opérateur '+' pour mon objet 'vect', qui devra additionner tous les objets pointés par son vector 'x' avec ceux pointés par un autre vect.
pour celà j'alloue dynamiquement un espace mémoire de type 'vect', puis je boucle sur le tableau, en espérant que cette ligne a l'intérieur de la boucle soit correcte...
puis je retourne une référence sur mon objet dynamique avec 'return *p;'
maintenant imaginons que j'utilise cet opérateur dans une autre fonction :
{
vect a,b,c;
a = b + c;
}
comment a la sortie de la fonction libérer la mémoire alouée ??
merci
La solution que j'utilise pour ce genre de truc c'est de faire de vect une classe de valeur, c'est-à-direune classe possédant : -un constructeur par défaut -un constructeur de copie -une surcharge d'affectation -une surcharge de == et ! Ensuite, plus de new vect mais par exemple dans + :
Attention pas de référence sur le résultat ------------------------------------------
le resultat est copié au return, il y a ensuite moyen de limiter le nombre de copies en n'ayant que des pointeurs comme attributs de vect et en utilisant un comptage de références : la copie fait pointer sur le même et dès qu'on change le contenu alors là on fait une copie
en fait ta classe vect ets une classe de valeurs, le plus simple est de se débrouiller pour pouvoir l'utiliser sans jamais faire appel à un new
notes qu'avec cette solution, on peut ecrire :
vect a = b + c + d ;
la suite est un petit exemple avec des attributs bidons mais qui fait le job :
#include <iostream> #include <stdlib.h>
using namespace std ;
// on compte les constructions et on décompte les destructions int nombreConstruitPasDetruit = 0 ;
class vect { public: vect() { cout << "une construction n" ; nombreConstruitPasDetruit++ ; }
vect(const int _x, const int _y) : x(_x), y(_y) { cout << "une construction n" ; nombreConstruitPasDetruit++ ;
// normalement ici, ya plus d'objets cout << nombreConstruitPasDetruit << "n" ;
}
salut,
j'ai un petit probleme avec la gestion d'une mémoire allouée
dynamiquement dans une fonction
vect &
vect::operator+(const vect &v) const
{
vect *p = new vect;
for(unsigned int i=0; i<x.size(); i ++)
{
*(p->x[i]) = (*x[i] + *(v.x[i]));
}
return *p;
}
imaginons que 'vect' soit un objet comprenant un vector 'x' qui lui même
contient un ensemble de pointeurs sur des objets dont la nature nous
importe peut (nous savons qu'ils ont un opérateur '+' défini)
je veux définir l'opérateur '+' pour mon objet 'vect', qui devra
additionner tous les objets pointés par son vector 'x' avec ceux pointés
par un autre vect.
pour celà j'alloue dynamiquement un espace mémoire de type 'vect', puis
je boucle sur le tableau, en espérant que cette ligne a l'intérieur de
la boucle soit correcte...
puis je retourne une référence sur mon objet dynamique avec 'return *p;'
maintenant imaginons que j'utilise cet opérateur dans une autre fonction :
{
vect a,b,c;
a = b + c;
}
comment a la sortie de la fonction libérer la mémoire alouée ??
merci
La solution que j'utilise pour ce genre de truc c'est de faire de vect
une classe de valeur, c'est-à-direune classe possédant :
-un constructeur par défaut
-un constructeur de copie
-une surcharge d'affectation
-une surcharge de == et !
Ensuite, plus de new vect mais par exemple dans + :
Attention pas de référence sur le résultat
------------------------------------------
le resultat est copié au return, il y a ensuite moyen de limiter le
nombre de copies en n'ayant que des pointeurs comme attributs de vect et
en utilisant un comptage de références : la copie fait pointer sur le
même et dès qu'on change le contenu alors là on fait une copie
en fait ta classe vect ets une classe de valeurs, le plus simple est de
se débrouiller pour pouvoir l'utiliser sans jamais faire appel à un new
notes qu'avec cette solution, on peut ecrire :
vect a = b + c + d ;
la suite est un petit exemple avec des attributs bidons mais qui fait le
job :
#include <iostream>
#include <stdlib.h>
using namespace std ;
// on compte les constructions et on décompte les destructions
int nombreConstruitPasDetruit = 0 ;
class vect {
public:
vect()
{
cout << "une construction n" ;
nombreConstruitPasDetruit++ ;
}
vect(const int _x, const int _y)
: x(_x), y(_y)
{
cout << "une construction n" ;
nombreConstruitPasDetruit++ ;
j'ai un petit probleme avec la gestion d'une mémoire allouée dynamiquement dans une fonction
vect & vect::operator+(const vect &v) const { vect *p = new vect; for(unsigned int i=0; i<x.size(); i ++) { *(p->x[i]) = (*x[i] + *(v.x[i])); } return *p; }
imaginons que 'vect' soit un objet comprenant un vector 'x' qui lui même contient un ensemble de pointeurs sur des objets dont la nature nous importe peut (nous savons qu'ils ont un opérateur '+' défini)
je veux définir l'opérateur '+' pour mon objet 'vect', qui devra additionner tous les objets pointés par son vector 'x' avec ceux pointés par un autre vect.
pour celà j'alloue dynamiquement un espace mémoire de type 'vect', puis je boucle sur le tableau, en espérant que cette ligne a l'intérieur de la boucle soit correcte...
puis je retourne une référence sur mon objet dynamique avec 'return *p;'
maintenant imaginons que j'utilise cet opérateur dans une autre fonction :
{
vect a,b,c;
a = b + c;
}
comment a la sortie de la fonction libérer la mémoire alouée ??
merci
La solution que j'utilise pour ce genre de truc c'est de faire de vect une classe de valeur, c'est-à-direune classe possédant : -un constructeur par défaut -un constructeur de copie -une surcharge d'affectation -une surcharge de == et ! Ensuite, plus de new vect mais par exemple dans + :
Attention pas de référence sur le résultat ------------------------------------------
le resultat est copié au return, il y a ensuite moyen de limiter le nombre de copies en n'ayant que des pointeurs comme attributs de vect et en utilisant un comptage de références : la copie fait pointer sur le même et dès qu'on change le contenu alors là on fait une copie
en fait ta classe vect ets une classe de valeurs, le plus simple est de se débrouiller pour pouvoir l'utiliser sans jamais faire appel à un new
notes qu'avec cette solution, on peut ecrire :
vect a = b + c + d ;
la suite est un petit exemple avec des attributs bidons mais qui fait le job :
#include <iostream> #include <stdlib.h>
using namespace std ;
// on compte les constructions et on décompte les destructions int nombreConstruitPasDetruit = 0 ;
class vect { public: vect() { cout << "une construction n" ; nombreConstruitPasDetruit++ ; }
vect(const int _x, const int _y) : x(_x), y(_y) { cout << "une construction n" ; nombreConstruitPasDetruit++ ;
// normalement ici, ya plus d'objets cout << nombreConstruitPasDetruit << "n" ;
}
drkm
writes:
Loïc Joly wrote in message news:<cbckct$aol$...
[à propos de operator+()]
Ensuite, l'opérateur devrait retourner un objet, et non pas une référence ou un pointeur. Ca peut poser des problèmes de performance, puisque du coup l'objet va être copié, mais ce problème peut être réduit :
[...]
- Il est possible de retourner non pas un vecteur mais un objet qui se souvient de l'opération effectuée, et ne va réellement additionner que quand on va accèder au contenu, tout en faisant cette gymnastique à la compilation (voir par exemple blitz::tiny_vector sur www.oonumerics.org, se munir d'une aspirine)
C'est la solution consacrée.
Porte-t-elle un nom ? J'ai jeté un coup d'oeil au tiny_vector de Blitz, mais cela est plutôt ardu pour découvrir une telle technique. Peut-être as-tu l'une ou l'autre référence ?
Ca m'a l'air en fait assez proche du Proxy, non ?
--drkm
kanze@gabi-soft.fr writes:
Loïc Joly <loic.actarus.joly@wanadoo.fr> wrote in message
news:<cbckct$aol$1@news-reader3.wanadoo.fr>...
[à propos de operator+()]
Ensuite, l'opérateur devrait retourner un objet, et non pas une
référence ou un pointeur. Ca peut poser des problèmes de performance,
puisque du coup l'objet va être copié, mais ce problème peut être
réduit :
[...]
- Il est possible de retourner non pas un vecteur mais un objet qui se
souvient de l'opération effectuée, et ne va réellement additionner que
quand on va accèder au contenu, tout en faisant cette gymnastique à la
compilation (voir par exemple blitz::tiny_vector sur
www.oonumerics.org, se munir d'une aspirine)
C'est la solution consacrée.
Porte-t-elle un nom ? J'ai jeté un coup d'oeil au tiny_vector de
Blitz, mais cela est plutôt ardu pour découvrir une telle technique.
Peut-être as-tu l'une ou l'autre référence ?
Ensuite, l'opérateur devrait retourner un objet, et non pas une référence ou un pointeur. Ca peut poser des problèmes de performance, puisque du coup l'objet va être copié, mais ce problème peut être réduit :
[...]
- Il est possible de retourner non pas un vecteur mais un objet qui se souvient de l'opération effectuée, et ne va réellement additionner que quand on va accèder au contenu, tout en faisant cette gymnastique à la compilation (voir par exemple blitz::tiny_vector sur www.oonumerics.org, se munir d'une aspirine)
C'est la solution consacrée.
Porte-t-elle un nom ? J'ai jeté un coup d'oeil au tiny_vector de Blitz, mais cela est plutôt ardu pour découvrir une telle technique. Peut-être as-tu l'une ou l'autre référence ?
Ca m'a l'air en fait assez proche du Proxy, non ?
--drkm
Loïc Joly
drkm wrote:
Porte-t-elle un nom ? J'ai jeté un coup d'oeil au tiny_vector de Blitz, mais cela est plutôt ardu pour découvrir une telle technique. Peut-être as-tu l'une ou l'autre référence ?
L'excellent "C++ template, the complete guide " de Josuttis et Vandevoorde en parle.
-- Loïc
drkm wrote:
Porte-t-elle un nom ? J'ai jeté un coup d'oeil au tiny_vector de
Blitz, mais cela est plutôt ardu pour découvrir une telle technique.
Peut-être as-tu l'une ou l'autre référence ?
L'excellent "C++ template, the complete guide " de Josuttis et
Vandevoorde en parle.
Porte-t-elle un nom ? J'ai jeté un coup d'oeil au tiny_vector de Blitz, mais cela est plutôt ardu pour découvrir une telle technique. Peut-être as-tu l'une ou l'autre référence ?
L'excellent "C++ template, the complete guide " de Josuttis et Vandevoorde en parle.
-- Loïc
darkman_spam
Loïc Joly wrote in message <cc4ctg$l2f$:
drkm wrote:
Porte-t-elle un nom ? J'ai jeté un coup d'oeil au tiny_vector de Blitz, mais cela est plutôt ardu pour découvrir une telle technique. Peut-être as-tu l'une ou l'autre référence ?
L'excellent "C++ template, the complete guide " de Josuttis et Vandevoorde en parle.
Merci.
Peut-être avec l'été vais-je enfin me décider à le lire. Depuis le temps que je le souhaite ...
--drkm
Loïc Joly wrote in message <cc4ctg$l2f$1@news-reader2.wanadoo.fr>:
drkm wrote:
Porte-t-elle un nom ? J'ai jeté un coup d'oeil au tiny_vector de
Blitz, mais cela est plutôt ardu pour découvrir une telle technique.
Peut-être as-tu l'une ou l'autre référence ?
L'excellent "C++ template, the complete guide " de Josuttis et
Vandevoorde en parle.
Merci.
Peut-être avec l'été vais-je enfin me décider à le lire. Depuis le
temps que je le souhaite ...
Porte-t-elle un nom ? J'ai jeté un coup d'oeil au tiny_vector de Blitz, mais cela est plutôt ardu pour découvrir une telle technique. Peut-être as-tu l'une ou l'autre référence ?
L'excellent "C++ template, the complete guide " de Josuttis et Vandevoorde en parle.
Merci.
Peut-être avec l'été vais-je enfin me décider à le lire. Depuis le temps que je le souhaite ...
--drkm
kanze
Loïc Joly wrote in message news:<cc4ctg$l2f$...
drkm wrote:
Porte-t-elle un nom ?
À vrai dire, pas que je sache. Mais c'est un problème que je n'ai suivi que de loin, étant donné qu'il a peu d'application pratique dans les domaines où je travaille.
J'ai jeté un coup d'oeil au tiny_vector de Blitz, mais cela est plutôt ardu pour découvrir une telle technique. Peut-être as-tu l'une ou l'autre référence ?
L'excellent "C++ template, the complete guide " de Josuttis et Vandevoorde en parle.
Ils en parlent de l'implémentation à templates. La technique est bien plus ancienne que les templates (j'en ai entendu parler déjà en 1992, ou quelque part par là), et marche aussi bien avec des fonctions virtuelles. En fait, j'ai fait un benchmark il y a cinq ou six ans, avec Sun CC 4.2, et curieusement, c'était la version avec fonctions virtuelles qui était la plus rapide.
-- James Kanze GABI Software http://www.gabi-soft.fr 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
Loïc Joly <loic.actarus.joly@wanadoo.fr> wrote in message
news:<cc4ctg$l2f$1@news-reader2.wanadoo.fr>...
drkm wrote:
Porte-t-elle un nom ?
À vrai dire, pas que je sache. Mais c'est un problème que je n'ai suivi
que de loin, étant donné qu'il a peu d'application pratique dans les
domaines où je travaille.
J'ai jeté un coup d'oeil au tiny_vector de Blitz, mais cela est
plutôt ardu pour découvrir une telle technique. Peut-être as-tu
l'une ou l'autre référence ?
L'excellent "C++ template, the complete guide " de Josuttis et
Vandevoorde en parle.
Ils en parlent de l'implémentation à templates. La technique est bien
plus ancienne que les templates (j'en ai entendu parler déjà en 1992, ou
quelque part par là), et marche aussi bien avec des fonctions
virtuelles. En fait, j'ai fait un benchmark il y a cinq ou six ans, avec
Sun CC 4.2, et curieusement, c'était la version avec fonctions
virtuelles qui était la plus rapide.
--
James Kanze GABI Software http://www.gabi-soft.fr
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
À vrai dire, pas que je sache. Mais c'est un problème que je n'ai suivi que de loin, étant donné qu'il a peu d'application pratique dans les domaines où je travaille.
J'ai jeté un coup d'oeil au tiny_vector de Blitz, mais cela est plutôt ardu pour découvrir une telle technique. Peut-être as-tu l'une ou l'autre référence ?
L'excellent "C++ template, the complete guide " de Josuttis et Vandevoorde en parle.
Ils en parlent de l'implémentation à templates. La technique est bien plus ancienne que les templates (j'en ai entendu parler déjà en 1992, ou quelque part par là), et marche aussi bien avec des fonctions virtuelles. En fait, j'ai fait un benchmark il y a cinq ou six ans, avec Sun CC 4.2, et curieusement, c'était la version avec fonctions virtuelles qui était la plus rapide.
-- James Kanze GABI Software http://www.gabi-soft.fr 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
drkm
writes:
Ils en parlent de l'implémentation à templates. La technique est bien plus ancienne que les templates (j'en ai entendu parler déjà en 1992, ou quelque part par là), et marche aussi bien avec des fonctions virtuelles. En fait, j'ai fait un benchmark il y a cinq ou six ans, avec Sun CC 4.2, et curieusement, c'était la version avec fonctions virtuelles qui était la plus rapide.
Tu as deux codes équivalents, l'un utilisant des modèles, et l'autre les mécanismes virtuels. Et le second est le plus rapide. C'est bien cela ? Cela me paraît étrange. Te souviens-tu d'où venait la différence de temps ?
--drkm
kanze@gabi-soft.fr writes:
Ils en parlent de l'implémentation à templates. La technique est bien
plus ancienne que les templates (j'en ai entendu parler déjà en 1992, ou
quelque part par là), et marche aussi bien avec des fonctions
virtuelles. En fait, j'ai fait un benchmark il y a cinq ou six ans, avec
Sun CC 4.2, et curieusement, c'était la version avec fonctions
virtuelles qui était la plus rapide.
Tu as deux codes équivalents, l'un utilisant des modèles, et l'autre
les mécanismes virtuels. Et le second est le plus rapide. C'est bien
cela ? Cela me paraît étrange. Te souviens-tu d'où venait la
différence de temps ?
Ils en parlent de l'implémentation à templates. La technique est bien plus ancienne que les templates (j'en ai entendu parler déjà en 1992, ou quelque part par là), et marche aussi bien avec des fonctions virtuelles. En fait, j'ai fait un benchmark il y a cinq ou six ans, avec Sun CC 4.2, et curieusement, c'était la version avec fonctions virtuelles qui était la plus rapide.
Tu as deux codes équivalents, l'un utilisant des modèles, et l'autre les mécanismes virtuels. Et le second est le plus rapide. C'est bien cela ? Cela me paraît étrange. Te souviens-tu d'où venait la différence de temps ?