HelloWindow 对象是否被删除?

Is HelloWindow object deleted?

我在 GNOME Builder 上创建了一个示例 GTKMM 项目。很棒的是,为我的示例项目自动生成了示例 hello world 代码。由于 C++ 源文件分为三个部分:

我已经在单个 cpp 文件中修改了我的示例代码以进行演示:

#include <iostream>

#include <gtkmm.h>

using std::cout;

using Gtk::Application;
using Gtk::Window;
using Gtk::Box;
using Gtk::Button;
using Gtk::Label;

class HelloWindow : public Window
{
    Box    box;
    Button button;
    Label  label;

public:
    HelloWindow();
    ~HelloWindow();
};

HelloWindow::HelloWindow()
    : Glib::ObjectBase("HelloWindow")
    , Window()
    , box(Gtk::ORIENTATION_VERTICAL)
    , button("Clickable button")
    , label("Hello World!")
{
    set_default_size(320, 240);

    bool expand(true), fill(true);
    box.pack_start(label, expand, fill);
    box.pack_end(button, expand, fill);

    add(box);

    show_all();
}

HelloWindow::~HelloWindow()
{
    cout << "Object successfully destructed!\n";
}

static void
on_activate(Glib::RefPtr<Application> app)
{
    Window *window = app->get_active_window();

    if (not window) {
        window = new HelloWindow();
        window->set_application(app);
        app->add_window(*window);
    }

    window->present();
}

int main()
{
    auto app = Application::create("io.test.window-state-event");

    app->signal_activate().connect(sigc::bind(&on_activate, app));

    return app->run();
}

关于上述代码的一个有趣的部分是 app 连接到 on_activate 信号,这意味着用户只能 运行 该程序的一个实例。如果他尝试 运行 另一个实例,则会显示之前的 运行ning window。

但是,在 on_activate() 上使用了 new 关键字,这让我有点困惑。当用户关闭 HelloWorld window 时,对象真的被删除了吗?我对 C++ new 关键字的了解是,必须记住 delete 使用前一个关键字分配的任何对象。

此外,析构函数消息“对象已成功销毁!” window 关闭时不打印。

可能存在故意泄漏,但它是“受控的”。作者知道这个方法只会被调用一次。作者还知道内存需要在应用程序的整个生命周期内处于活动状态。当应用程序关闭时,该内存将以一种或另一种方式释放(尽管永远不会调用析构函数,但在这种情况下,不需要做任何必要的事情)

这种场景下完全没问题。

如果你想确保 Window 对象被删除,你可以保留 Windowunique_ptr 它会自行处理(感谢 @underscore_d评论):

#include <memory>

static std::unique_ptr<Window> window;

static void
on_activate(Glib::RefPtr<Application> app)
{
    if (!window) {
        window = std::make_unique<HelloWindow>();
        window->set_application(app);
        app->add_window(*window);
    }

    window->present();
}

int main()
{
    auto app = Application::create("io.test.window-state-event");
    app->signal_activate().connect(sigc::bind(&on_activate, app));
    return app->run();
}

归根结底,我确信作者希望让这个“Hello, World”示例简单明了,不想添加一些实际上并不重要的代码 需要 以使其简单明了。

查看 GTKMM 文档中关于 managed widgets 的部分。您应该使用 Gtk::make_managed:

的一些变体
if (!window) {
    window = Gtk::make_managed<HelloWindow>();
    window->set_application(app);
    app->add_window(*window);
}

这样,window 的生命周期将由应用程序管理。