Ребята из Gtkmm сравнивают Glib::RefPtr
с std::auto_ptr<>
:
Glib::RefPtr
— это умный указатель. В частности, это смарт-пойнтер с подсчетом ссылок. Возможно, вы знакомы сstd::auto_ptr<>
, который также является умным указателем, ноGlib::RefPtr<>
намного проще и полезнее.
Но по какой-то странной причине я не могу работать с RefPtr
. Тот же код прекрасно работает с auto_ptr
.
В следующем коде SmartPtr
— это просто заполнитель для одного из этих двух умных указателей.
#include <gtkmm.h>
#include <iostream>
#include <tr1/memory>
struct WindowHolder {
SmartPtr<Gtk::Window> ptr;
WindowHolder()
: ptr(new Gtk::Window)
{
ptr->signal_delete_event().connect(sigc::mem_fun(*this, &WindowHolder::reset));
ptr->show_all();
}
bool reset(GdkEventAny* event)
{
Gtk::Main::quit();
}
};
int main(int argc, char *argv[])
{
Gtk::Main kit(argc, argv);
WindowHolder w;
kit.run();
}
При компиляции я сначала определяю SmartPtr
как Glib::RefPtr
, а затем как std::auto_ptr
.
$ g++ '-DSmartPtr=Glib::RefPtr' `pkg-config --cflags --libs gtkmm-3.0` main.cc && ./a.out
(main:22093): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed
$ g++ '-DSmartPtr=std::auto_ptr' `pkg-config --cflags --libs gtkmm-3.0` main.cc && ./a.out
$
Проблема в том, что GLib-GObject-CRITICAL
. В моем реальном приложении это не просто одна строка, а целая их куча. Во второй версии с std::auto_ptr
все хорошо деструктируется.
Как ни странно, код отлично работает в GTK 2:
$ g++ '-DSmartPtr=Glib::RefPtr' `pkg-config --cflags --libs gtkmm-2.4` main.cc && ./a.out
$
Я не хочу зависеть от std::auto_ptr
, потому что он устарел, и я также не хочу работать с необработанным указателем, потому что тогда деструкторы должны вручную удалять указатели, что добавляет дополнительную сложность...
Мои вопросы:
- Почему вызывает
Glib::RefPtr
это "критическое предупреждение" (вероятно, двойное бесплатное)? - Почему это работает с gtkmm 2.4, но не работает с 3.0?
- Можно ли исправить код с
Glib::RefPtr
и gtkmm 3.0? - Как мне вообще вести себя в таких ситуациях?