C++ – gtkmm Manage/Add vs Smart Pointers

cgtkobject-orientedsmart-pointer

gtkmm provides lifetime management of widgets using

Gtk::Widget* aWidget = Gtk::manage(new Widget()); 

Gtk::Widget.add(*aWidget);

This delegates lifetime management of aWidget to its container widget.

We also have several types of smart pointers, particular the C++ 11 smart pointers templates, which I use everywhere.

I find the manage/add syntax easier and cleaner to use, but it's not part of the C++ Standard, it's a gtkmm specific feature, which makes me think I should stick to std::shared_ptr, etc.

So I'm wondering what are the advantages/disadvantages of smart pointers vs the gtkmm manage/add model (aside from cases where you need the reference after the owner container has been deleted, or when you have a top level widget that has no containing widget).

Best Answer

Gtk::manage() solves the specific problem of lifetime management for hierarchies of widgets. And it solves it well.

Smart pointers (std::shared_ptr in particular) have broader application range, and therefore will be less efficient when used to address this specific problem. Lifetime management for hierarchies of widgets can be solved with shared_ptr, but it will be:

  • not as concise as using manage() (as you pointed out yourself);
  • less efficient in terms of memory usage, since using shared_ptrs will introduce memory overhead: shared_ptr has a memory footprint of its reference to its reference-count, which will use size - as opposed to manage(), which uses variables such as Gtk::Object.referenced_ that are part of your Widget base class already at all times. So, if you have a significant number of Widgets, that size difference might become an issue worth considering;
  • not as mainstream as using manage() in gtkmm (which has quite a few consequences, including clarity and maintainability).

As of idea of favoring std::shared_ptr over Gtk::manage() because shared_ptr is part of C++ Standard, while manage() is not - I'm not sure it is going to be a game changer for average application, as by not using manage() you don't cut your dependency on Gtk anyways. So your application is not going to gain any better portability if you'd go for shared_ptr.

I would rather leverage native gtkmm API, for sake of clarity and efficiency.

P.S.: There is actually a smart pointer Glib::RefPtr, which handles lifetime management for certain gtkmm objects. Again, as it is a feature native to Glib, it leverages built-in facilities of Glib::ObjectBase, and is therefore more efficient then std::shared_ptr for certain applications, for the reasons explained in the 2nd point above.