c++ - 使用 offsetof() 从成员变量中获取所有者对象

标签 c++ pointers member offsetof

我想在这里实现“GetParent()”函数-

class ChildClass;

class ParentClass
{
public:
    ....
    ChildClass childObj;
    ....
};

class ChildClass
{
    friend class ParentClass;
private:
    ChildClass();

public:
    ParentClass* GetParent();
};

我试图创建一个私有(private)成员变量来存储指向父对象的指针。 但是,此方法需要额外的内存。

class ChildClass
{
    friend class ParentClass;

private:
    ChildClass();

    ParentClass* m_parent;

public:
    ParentClass* GetParent()
    {
        return m_parent;
    }
};

所以我使用了 offsetof() 宏(调用 offsetof() 的性能成本可以忽略),但我不确定这种方法是否安全。它适用于所有情况吗?有没有更好的主意?

class ChildClass
{
public:
    ParentClass* GetParent()
    {
        return reinterpret_cast<ParentClass*>(
            reinterpret_cast<int8_t*>(this) - offsetof(ParentClass, childObj)
            );
    }
};

最佳答案

使用 offsetof 计算容器对象的地址是安全的,因为它可以工作。 offsetof 在 C 中通常用于此目的。参见例如 container_of Linux 内核中的宏。

如果有一个 ChildClass 实例不是那个特定的成员变量,那么它可能是不安全的,那么你手上就有未定义的行为。当然,由于构造函数是私有(private)的,您应该能够防止这种情况发生。

它不安全的另一个原因是它 has undefined behaviour如果容器类型不是 standard layout type .

因此,只要您考虑到注意事项,它就可以正常工作。但是,您的实现已损坏。 offsetof 宏的第二个参数必须是成员的名称。在这种情况下,它必须是 childObj 而不是 e[index] 这不是成员的名字。

此外(如果我错了,也许有人会纠正我,但我认为)在进行指针运算之前转换为不相关的类型 uint8_t* 然后再转换为另一个不相关的类型似乎有点危险的。我建议使用 char* 作为中间类型。保证 sizeof(char) == 1 并且它有关于别名和没有陷阱表示的特殊异常(exception)。

可能值得一提的是,指针算法的这种使用——或除数组使用以外的任何使用——是not defined。按标准。严格来说,这使得 offsetof 毫无用处。不过,指针在数组之外得到广泛使用,因此在这种情况下可以忽略缺乏标准支持。

关于c++ - 使用 offsetof() 从成员变量中获取所有者对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34511712/

相关文章:

c++ - 正确使用 GetComputerName - 我是否需要为空字符保留额外的空间

c++ - 如何在 C++ 中添加延迟

c - 访问结构中的字符指针字段

swift - 用存储的属性覆盖

c++ - 用C++优化二维空间中粒子运动的蒙特卡罗模拟

c++ - 在文件中找到字符串后替换它旁边的字符

delphi - Delphi 中取消引用和分配指针的语法

c++函数指针内联

list - 检查某些东西是否是 Prolog 中嵌套列表中的成员

C++ 可以不继承成员吗?