Any thoughts on this C++ smart pointer issue?
Jeff Franks
jcfranks at tpg.com.au
Sun Nov 28 01:57:38 CET 2004
Brian (and other C++ enthusiast's),
There is one smart pointer issue that may come up when you see the first
XFC development tarballs, so I thought I'd seek your preference now, if any.
Like Gtkmm, XFC uses a smart pointer (Xfc::Pointer<>) to manage GTK+
reference counting, but unlike Gtkmm, XFC doesn't enforce its usage. As
things stand, in XFC it's equally valid to use either a smart pointer to
manage all reference counting, or to manage reference counting yourself
by calling ref() and unref(). The beauty of Xfc::Pointer<> is that
(internally) it knows if an object is a GObject or floating widget and
handles its reference counting and sinking appropriately (there is no
sink function in XFC).
Gtkmm forces the use of a smart pointer on all GObjects. For example,
Gtkmm::Gtk::AccelGroup is derived from Gtkmm::Glib::Object and so it has
an initial reference that must be cleared. For objects like these Gtkmm
provides no public constructors. The default constructor is protected
and is called by a public 'create' function that returns a smart
pointer. Thus ensuring that a programmer doesn't forget to unreference
the object. For example, you can only construct a Gtkmm::Gtk::AccelGroup
with this create function:
static Glib::RefPtr<AccelGroup> create();
like this:
Glib::RefPtr<Gtk::AccelGroup> accel_group = Gtk::AccelGroup::create();
// use accel_group, it is unreferenced when it goes out of scope
My only concern with this approach is that the smart pointer is template
class with some small overhead. The more you use smart pointers the
bigger the overhead. Optimally, managing reference counting yourself is
better but not as convenient, and there are times when this was
preferred. So far I have taken the view that the programmer should have
the choice. An experienced GTK+ programmer should feel quite comfortable
calling ref() and unref() on an object. Whereas a new programmer that
isn't sure can just use a smart pointer.
Compared with Gtkmm, you can create and use a Xfc::Gtk::AccelGroup
either like this:
Pointer<Gtk::AccelGroup> accel_group = new Gtk::AccelGroup;
// use accel_group, it is unreferenced when it goes out of scope
or like this:
Gtk::AccelGroup *accel_group = new Gtk::AccelGroup;
// use accel_group
accel_group->unref();
The only disadvantage with this approach is that it requires the
programmer to be aware of the class a new object derives from:
Xfc::G::Object (never floating) or Xfc::Gtk::Object (floating). All the
reference counting rules are identical to GTK+. So if you pass a
floating object to an owner, or add a widget to a container, you don't
need to worry about reference counting or smart pointers. If you pass a
G::Object to an owner, like a Gtk::AccelGroup to a window, you have to
explicitly unreference it after if you are not using a smart pointer.
This only applies to object construction. All class methods that return
a pointer to an object that must be unreferenced return as a smart pointer.
Jeff Franks.
More information about the Xfce4-dev
mailing list