7

来自 Gtkmm 的人正在比较Glib::RefPtrstd::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();
}

编译的时候,我先定义SmartPtrGlib::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因为它已被弃用,我也不想使用原始指针,因为这样析构函数必须手动删除指针,这会增加额外的复杂性......

我的问题是:

  1. 为什么会导致Glib::RefPtr这个“严重警告”(可能是双重免费)?
  2. 为什么它适用于 gtkmm 2.4 但不适用于 3.0?
  3. 我可以用Glib::RefPtrgtkmm 3.0 修复代码吗?
  4. 我一般应该如何处理这种情况?
4

2 回答 2

5

Glib::RefPtr 不适合一般用途。当 API 强制您使用时,您应该使用它,但不是其他情况。GtkWindow(或 Gtk::Window)有它自己的奇数内存管理,它与 RefPtr 并不真正兼容。

如果你想要一个通用的智能指针,试试 std::shared_ptr 或 std::unique_ptr。或者你可以在 boost 中找到一些东西。

于 2012-04-17T20:14:17.093 回答
4

引用计数太低,您可以通过添加ptr->reference()after来修复它ptr->show_all()。我有一个解释,但要持保留态度:

  • Glib::RefPtr 最初不会增加其对象的引用计数。
  • GtkWindow 最初的引用计数为 1。
  • 当您的窗口关闭时,该库会减少其 GtkWindow 的引用计数一次。
  • 由于 GtkWindow 的计数为零,因此它被销毁。
  • kit.run() 看到没有更多的窗口,返回。
  • w 超出范围并且 RefPtr 的对象计数减少,从而导致错误。

不幸的是,我不能真正回答 #2 或 #4,因为 gtk/gtkmm 的这个区域仍然有点神秘(对我来说)。

参考:http ://www.gtkforums.com/viewtopic.php?t=2412

于 2012-04-14T23:43:44.520 回答