[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[linux] Re: [C++] Re: C++ / C re-question
Hello !
On Fri, Jul 13, 2001 at 09:05:19AM +0200, Pascal Bleser wrote:
[.../...]
> En général, vaut mieux éviter ce genre de trucs (et surtout char*) et utiliser
> soit std::string de la STL, soit un smart pointer, du genre
J'ai du mal à comprendre pourquoi les « novices » du C++ ¹ ont si peur
de 'std::string' ... et pourquoi les professeurs ne les poussent pas
plus à comprendre le mécanisme.
Pour ceux qui ne le savent pas, copier une instance de 'std::string' (ou
la passer par valeur) reste _très performant_. Certainement plus
performant que la solution traditionnelle du C, où l'on fait des
'strdup' et des 'free' à tire-larigot. En effet, les chaînes de
'std::string' sont copy-on-write, c'est-à-dire qu'elles ne sont copiées
que lorsque c'est _strictement_ nécessaire, donc lors des rares
modifications.
> template <class T>
> class SmartPointer {
> private:
> T* pointer_;
> public:
> SmartPointer(T* pointer) : pointer_(pointer) { }
> SmartPointer(const SmartPointer& sp)
> : pointer_(sp.pointer) { }
>
> virtual ~SmartPointer() {
> delete pointer_;
> }
>
> T* operator->() const {
> return pointer_;
> }
> };
>
> L'astuce étant que lorsque le SmartPointer est out of scope, il va faire
> un delete sur le pointer.
Pas bien ... il manque un compteur d'instance par pointeur ;)
Pour ceux que cela « tracasse » : la classe SmartPointer contient un
constructeur de copie, et donc va donc être copiée à tout va (retours de
fonction, variables locales, etc.). Mais l'expression 'delete pointer_;'
va être exécutée dès que la _1ere_ instance va être out of scope ! Donc,
les autres pointeurs deviendront indéterminés, et plusieurs 'delete'
seront faits sur la même zone mémoire.
Mais l'idée reste astucieuse : j'ai un peu étoffé la classe de Pascal,
(et j'ai fait un petit programme de test, pour éviter les mauvaises
surprises), et je l'ai mise en attachement. Si qqn a des commentaires,
qu'il n'hésite pas à me le faire savoir. ²
Cu,
Dash.
¹ Bon, OK, j'en fais partie.
² En privé, sinon il va vraîment falloir créer une liste C++ sur
linuxbe !
--
Convictions are more dangerous enemies of truth than lies.
-- Nietzsche
--
Damien Diederen
dash@linuxbe.org
http://users.swing.be/diederen/
#include <iostream>
#include <string>
template <class T>
struct SmartPointerNode {
public:
SmartPointerNode (T* pointer) :
mPointer (pointer), mCount (1) { }
private:
SmartPointerNode (const SmartPointerNode& o)
{ }
public:
T* mPointer;
int mCount;
};
template <class T>
class SmartPointer {
public:
SmartPointer (T* pointer)
{ mNode = new SmartPointerNode<T> (pointer); }
SmartPointer (const SmartPointer& o) :
mNode (o.mNode)
{ ++ mNode->mCount; }
~SmartPointer () {
if (-- mNode->mCount == 0) {
delete mNode->mPointer;
delete mNode;
}
}
T* operator-> () const
{ return mNode->mPointer; }
private:
SmartPointerNode<T>* mNode;
};
class Foo {
public:
Foo () { cout << "Foo constructed" << endl; }
~Foo () { cout << "Foo destroyed" << endl; }
void sayHello (const std::string& from) const
{ cout << "Foo says Hello from " << from << endl; }
};
typedef SmartPointer<Foo> FooPtr;
FooPtr makeFoo ()
{
FooPtr f = new Foo ();
f->sayHello ("makeFoo");
return f;
}
void useFoo (FooPtr sf)
{
FooPtr f = sf;
f->sayHello ("useFoo");
}
int main ()
{
FooPtr f = makeFoo ();
f->sayHello ("main");
useFoo (f);
return 0;
}