使用offsetof()从成员变量获取所有者对象 [英] Using offsetof() to get owner object from member variable

查看:142
本文介绍了使用offsetof()从成员变量获取所有者对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to implement 'GetParent()' function in here-

class ChildClass;

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

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

public:
    ParentClass* GetParent();
};

我尝试创建一个私有成员变量,该变量存储指向父对象的指针. 但是,此方法需要额外的内存.

I've tried to create a private member variable which stores pointer to parent object. However this method requires additional memory.

class ChildClass
{
    friend class ParentClass;

private:
    ChildClass();

    ParentClass* m_parent;

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

因此,我使用了offsetof()宏(可以忽略调用offsetof()的性能成本),但是我不确定这种方法是否安全.在每种情况下都可以使用吗?有更好的主意吗?

So I used offsetof() macro (performance costs of calling offsetof() can be ignored), but I'm not sure this approach is safe. Would it be work on every situation? Is there any better Idea?

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

推荐答案

在可以使用的意义上,使用offsetof计算容器对象的地址是 safe .为此,通常在C中使用offsetof.例如,参见 container_of 宏在Linux内核中.

Calculating the address of the container object using offsetof is safe in the sense that it can work. offsetof is commonly used in C for this purpose. See for example the container_of macro in Linux kernel.

从某种意义上说,如果存在一个ChildClass实例不是该特定成员变量的 ,那您就不安全了.当然,由于构造函数是私有的,因此您应该能够避免这种情况.

It can be unsafe in the sense that if there is a ChildClass instance that is not that particular member variable, then you have undefined behaviour on your hands. Of course, since the constructor is private, you should be able to prevent that.

不安全的另一个原因是,如果具有不确定的行为,容器类型不是标准布局类型.

Another reason why it's not safe is that it has undefined behaviour if the container type is not a standard layout type.

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

So, it can work as long as you take the caveats into account. Your implementation however, is broken. The second parameter of the offsetof macro must be the name of the member. In this case, it must be childObj and not e[index] which is not the name of the member.

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

Also (maybe someone will correct me if I'm wrong, but I think) casting to an unrelated type uint8_t* before doing the pointer arithmetic and then cast to yet another unrelated type seems a bit dangerous. I recommend using char* as the intermediate type. It is guaranteed that sizeof(char) == 1 and it has special exceptions about aliasing and not having trap representations.

值得一提的是,指针算术的这种使用-或除数组之外的任何其他使用-

It might be worth mentioning that this use - or any use other than use with arrays - of pointer arithmetic is not defined by the standard. Which strictly speaking makes offsetof useless. Still, pointers are widely used beyond arrays, so the lack of standard backing can in this case be ignored.

这篇关于使用offsetof()从成员变量获取所有者对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆