Gestion de la mémoire

Éléments graphiques

Gestion classique de la mémoire en C++
gtkmm autorise le programmeur à contrôler la durée de vie (c'est-à-dire, la construction et la destruction) de tout élément graphique de la même manière que celle de n'importe quel objet C++. Cette polyvalence autorise, soit l'utilisation des opérateurs new et delete pour créer et détruire les objets de manière dynamique, soit l'utilisation de données membres de classes régulières (qui sont détruites automatiquement quand la classe est détruite), soit l'utilisation d'instances locales (qui sont détruites dès que l'instance est hors de portée). Certaines boîtes à outils GUI C++ n'offrent pas cette souplesse : elles restreignent le programmeur à un sous-ensemble des fonctionnalités de gestion mémoire du C++.
Voici quelques exemples de gestion traditionnelle de la mémoire en C++ :

Éléments graphiques à portée de classe
Si un programmeur n'a pas besoin d'allocation dynamique de mémoire, il peut se servir d'éléments graphiques automatiques à portée de classe. Un des avantages des éléments graphiques automatiques à portée de classe est que la gestion de la mémoire est regroupée en un seul endroit. Le programmeur ne risque pas de fuites de mémoire en oubliant un delete sur un élément graphique.
The primary disadvantage of using class scope widgets is revealing the class implementation rather than the class interface in the class header.

#include <gtkmm/button.h>
#include <gtkmm/window.h>
class Foo : public Gtk::Window
{
private:
  Gtk::Button theButton;
  // will be destroyed when the Foo object is destroyed
};

Éléments graphiques à portée de fonction
If a programmer does not need a class scope widget, a function scope widget may also be used. The advantages to function scope over class scope are the increased data hiding and reduced dependencies.

{
  Gtk::Button aButton;
  aButton.show();
  ...
  app->run();
}

Allocation dynamique avec new et delete
Although, in most cases, the programmer will prefer to allow containers to automatically destroy their children using Gtk::manage() (see below), the programmer is not required to use Gtk::manage(). The traditional new and delete operators may also be used.

Gtk::Button* pButton = new Gtk::Button("Test");

// do something useful with pButton

delete pButton;

Here, the programmer deletes pButton to prevent a memory leak.

Éléments graphiques gérés
Alternatively, you can let a widget's container control when the widget is destroyed. In most cases, you want a widget to last only as long as the container it is in. To delegate the management of a widget's lifetime to its container, first create it with Gtk::manage() and pack it into its container with Gtk::Container::add(), Gtk::Box::pack_start(), or a similar method. Now the widget will be destroyed whenever its container is destroyed.

Allocation dynamique avec manage() et add()
gtkmm provides the manage() function and add() methods to create and destroy widgets. Every widget except a top-level window must be added or packed into a container in order to be displayed. The manage() function marks a widget so that when the widget is added to a container, the container becomes responsible for deleting the widget.

MyContainer::MyContainer()
{
  Gtk::Button* pButton = Gtk::manage(new Gtk::Button("Test"));
  add(*pButton); //add *pButton to MyContainer
}

Now, when objects of type MyContainer are destroyed, the button will also be deleted. It is no longer necessary to delete pButton to free the button's memory; its deletion has been delegated to the MyContainer object.
Of course, a top-level container will not be added to another container. The programmer is responsible for destroying the top-level container using one of the traditional C++ techniques. For instance, your top-level Window might just be an instance in your main() function.

Ressources partagées
Some objects, such as Gdk::Pixbufs and Pango::Fonts, are obtained from a shared store. Therefore you cannot instantiate your own instances. These classes typically inherit from Glib::Object. Rather than requiring you to reference and unreference these objects, gtkmm uses the Glib::RefPtr<> smartpointer. Cairomm has its own smartpointer, Cairo::RefPtr<>.
Objects such as Gdk::Pixbuf can only be instantiated with a create() function. For instance,

Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create_from_file(filename);

You have no way of getting a bare Gdk::Pixbuf. In the example, pixbuf is a smart pointer, so you can do this, much like a normal pointer:

int width = 0;
if(pixbuf)
{
  width = pixbuf->get_width();
}

When pixbuf goes out of scope an unref() will happen in the background and you don't need to worry about it anymore. There's no new so there's no delete.
If you copy a RefPtr, for instance

Glib::RefPtr<Gdk::Pixbuf> pixbuf2 = pixbuf;

, or if you pass it as a method argument or a return type, then RefPtr will do any necessary referencing to ensure that the instance will not be destroyed until the last RefPtr has gone out of scope.
Consultez cette annexe pour une information détaillée concernant les RefPtr.
If you wish to learn more about smartpointers, you might look in these books:
Bjarne Stroustrup, "The C++ Programming Language" Forth Edition - section 34.3
Nicolai M. Josuttis, "The C++ Standard Library" - section 4.2