C++:获取包含成员子对象的完整对象的地址
C++: Get adress of complete object containing member subobject
我有两个类,大致定义如下:
class Inner {
public:
bool is_first;
};
class Outer {
public:
char some_other_member;
Inner first;
Inner second;
}
我知道Inner
只存在于Outer
s内部,并且当且仅当相应的对象是first
成员而不是second
时,相应的布尔标志将设置为true
。
我正在寻找一种符合标准的方式来派生指向包含某些Inner
对象的Outer
对象的指针。当然,我可以在每个Inner
对象中存储一个指针,但由于Inner
类非常小,而且我有很多指针,这似乎是浪费内存(因此是宝贵的缓存(。
显然,编译器应该知道first
、second
和包含Outer
对象之间的内存偏移量。问题是:是否有一种符合标准的方法告诉编译器"获取偏移量,从指向Inner
的指针中减去它并使其成为Outer
指针"?
我知道我可以使用强制转换来void
Outer
是否将Inner
s作为基本子对象(例如这个( - 我非常觉得成员子对象应该可以做类似的事情?
您应该注意,从指向成员的指针获取指向父对象的指针的问题通常是无法解决的。
offsetof
和强制转换仅适用于标准布局类型。在其他情况下,它是未定义的行为。
例如,对于多个虚拟继承,它失败。在这种情况下,成员访问是通过比添加编译时偏移量更复杂的方式实现的。也许这实际上并不那么相关,因为它很少使用,但您明确要求符合标准。
没有一个解决方案是严格正确的,你违反了一些指针算术规则。但是,有一个实现定义的解决方案,它几乎总是按照您的期望执行
auto get_outer(Inner& i)
{
return (Inner*)(((uintptr_t)&i) - offsetof(Outer, first));
}
捕获是指针和整数类型转换是实现定义的。
这就是offsetof
的用途。
像这样:
Outer *Inner::getOuter() {
size_t offset = flag ? offsetof(Outer, first) : offsetof(Outer, second);
return reinterpret_cast<Outer *>(
reinterpret_cast<char *>(this) - offset);
}
请注意,您reinterpret_casting,因此您完全有责任知道自己在做什么。如果标志不同步,您将获得未定义的行为。
请注意,指针算术只允许在数组中使用,但 §6.9/4 ([basic.types]( 明确表示每个对象都存储在这样的unsigned char
数组中:
类型为
T
的对象的对象表示是类型T
的对象占用的 N 个unsigned char
对象的序列,其中N等于sizeof(T)
个。
在此数组中,定义了指针算术。但你需要确保你确实在分配范围内。
- 空基优化子对象的地址
- 对象地址是否保证是其类型对齐的倍数
- 更改保留指向其字段的原始指针的对象地址
- 指向未由对象地址初始化的对象的指针如何将值分配给类的数据成员
- 为什么存储对象地址在缓冲区中会导致内存泄漏并删除它们
- 尝试将派生类对象地址分配给基类指针的向量
- 如果类型相同,对象地址必须不同,但如果类型不同,地址可以相同
- 使用对象地址以及方法地址和签名调用C 成员函数
- 将派生的对象地址分配给基础指针和调用击路仪的机制
- 为什么写入临时字符串流对象只打印对象地址
- 依赖静态对象地址安全吗
- 获取引用指向的对象地址
- 传递对象地址时"Address expression must be an lvalue or a function designator"
- 在C++中存储对象地址的数据结构
- 从函数初始化对象地址
- 使用reintepret_cast解释对象地址
- 为什么基类指针总是指向基类,即使它持有派生类对象地址
- 是否可以将堆栈对象地址赋给placement new
- <<运算符重载不起作用;仍在打印对象地址
- 关于返回对象地址的困惑