You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在类声明中使用GLib的g_autoptr智能指针?

g_autoptr作为类成员变量的使用问题

背景与简化写法

之前使用std::unique_ptr搭配自定义删除器管理GLib对象的代码如下:

#include <glib.h>
#include <memory>

GError* error = nullptr;
std::unique_ptr<GDBusConnection, decltype(&g_object_unref)> conn(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error), &g_object_unref);
if (!conn) {
    printf("Couldn't get bus: %s", error ? error->message : "unknown error");
    g_clear_error(&error);
}

借助GLib的g_autoptr智能指针可以简化代码,无需手动指定删除器:

#include <glib.h>

g_autoptr(GError) error = nullptr;
g_autoptr(GDBusConnection) conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
if (!conn) {
    printf("Couldn't get bus: %s", error ? error->message : "unknown error");
}

类成员使用时的报错

尝试将g_autoptr声明为类成员变量时:

#include <glib.h>

class YourClass {
    YourClass();
    ~YourClass();

    // 其他成员
private:
    g_autoptr(GDBusConnection) _conn;
};

YourClass::YourClass() {
    g_autoptr(GError) error = nullptr;
    _conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
    if (!_conn) {
        printf("Couldn't get bus: %s", error ? error->message : "unknown error");
    }
}

GCC会抛出如下错误:

error: 'cleanup' attribute ignored [-Werror=attributes]
|     g_autoptr(GDBusConnection) _conn;

原因与解决方案

原因

g_autoptr的实现依赖GCC的__attribute__((cleanup))属性,该属性仅对自动存储期的变量(栈上局部变量)生效。类成员变量属于对象的一部分,存储在堆或对象所在的内存区域,不属于自动存储期,因此编译器会忽略这个属性,触发报错。

解决方案

  1. 手动管理生命周期:使用原始指针作为类成员,在类的析构函数中手动调用g_object_unref()清理资源:
class YourClass {
public:
    YourClass() : _conn(nullptr) {
        g_autoptr(GError) error = nullptr;
        _conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
        if (!_conn) {
            printf("Couldn't get bus: %s", error ? error->message : "unknown error");
        }
    }

    ~YourClass() {
        if (_conn) {
            g_object_unref(_conn);
        }
    }

private:
    GDBusConnection* _conn;
};
  1. 回归std::unique_ptr:继续使用std::unique_ptr作为类成员,搭配g_object_unref作为自定义删除器,兼顾自动清理和类成员场景:
#include <glib.h>
#include <memory>

class YourClass {
public:
    YourClass() {
        g_autoptr(GError) error = nullptr;
        _conn.reset(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error));
        if (!_conn) {
            printf("Couldn't get bus: %s", error ? error->message : "unknown error");
        }
    }

private:
    std::unique_ptr<GDBusConnection, decltype(&g_object_unref)> _conn{nullptr, &g_object_unref};
};
  1. GLib 2.74+扩展方案:如果使用GLib 2.74及以上版本,可以借助G_AUTOPTR_DECLARE_TYPE宏为自定义类型生成适配g_autoptr的代码,但对于内置的GObject类型,前两种方案依然是更直接的选择。

内容的提问来源于stack exchange,提问作者parsley72

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 07:31:11