来自Gtkmm的家伙是comparing Glib::RefPtrstd::auto_ptr<>:



但是出于某些奇怪的原因,我无法使用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修复代码吗?
  • 一般情况下,我应该如何处理?
  • 最佳答案

    引用计数太低,您可以通过在ptr->reference()之后添加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

    08-16 09:02