17Fermer19
BrunniLe 22/05/2013 à 12:11
Hmm ok je vois (pour la première partie en tous cas). Ca correspond probablement à ce que je m'étais amusé à implémenter :template<class T> class ref { T *ptr; unsigned *counter; void incref() { if (counter) (*counter)++; } void decref() { if (counter && --(*counter) == 0) delete ptr, delete counter; } public: ref() : ptr(0), counter(0) {} ref(const ref<T> &ref) : ptr(ref.ptr), counter(ref.counter) { incref(); } ref(T *ptr) : ptr(ptr) { counter = ptr ? new unsigned(1) : 0; } ~ref() { decref(); } ref<T> &operator = (const ref &ref) { // Using the same logic may free the original object if counter = 1 if (ref.ptr == ptr) return *this; // Else, do the equivalent of destructing "this" and constructing with "ref" decref(); ptr = ref.ptr, counter = ref.counter; incref(); return *this; } ref<T> &operator = (T *newPtr) { decref(); counter = (ptr = newPtr) ? new unsigned(1) : 0; return *this; } operator T* () const { return ptr; } T* operator -> () const { return ptr; } T& operator * () const { return *ptr; } bool operator == (const ref<T> &ref) const { return ref.ptr == ptr; } bool operator != (const ref<T> &ref) const { return ref.ptr != ptr; } };
Alors on n'a qu'à utiliser ref<Objet> à la place de Objet * pour une gestion automatique de la mémoire, et utiliser le modèle standard au besoin smile
class Image {
	const char *name;
public:
	Image(const char *name) : name(name) { cout << "Constructed " << name << endl; }
	~Image() { cout << "Destructed " << name << endl; }
	int getWidth() { return 42; }
};

ref<Image> g_image = new Image("1.png");

void method(Image *myImage) {
	cout << "Size is " << myImage->getWidth() << endl;
}

int main(int argc, const char * argv[]) {
	ref<Image> local;
	g_image = NULL; /* libération explicite */
	local = new Image("3.png"); /* affectation possible depuis un pointeur */
	method(local); /* passage à une fonction d'API n'utilisant pas ref<> */
	cout << "Locally: " << local->getWidth() << endl; /* Utilisation de ref<Image> comme une Image* */
	return 0;
}

png
=> Constructed 1.png
Destructed 1.png
Constructed 2.png
Size is 42
Locally: 42
Destructed 2.

Je pense que je vais choisir ça en fin de compte, ça me paraît assez facile à comprendre (juste dire aux débutants que s'ils veulent s'affranchir de la gestion de la mémoire ils n'ont qu'à utiliser ref<Truc> plutôt que Truc*) et comme ça marche pour tout sans polluer ceux qui ne veulent pas s'en servir, ça me paraît être un bon compromis. hehe