c++ - 计算包含对象的this指针

标签 c++ inner-classes pointer-arithmetic

以下可移植且符合标准的 C++ 是否始终返回“成功”?

#include <iostream>
#include <cstddef>

struct Containing {
    struct {
        Containing * get_containing () {
            return reinterpret_cast<Containing *> (
                (char *) this - offsetof (Containing, inner)
            );
        }
    } inner;
};


int main () {
    Containing c;
    std::cout
        << (c.inner.get_containing () == &c ? "success" : "fail")
        << std::endl;
}

最佳答案

#include <iostream>
#include <cstddef>

struct Containing {
    struct {
        Containing * get_containing () {
            return reinterpret_cast<Containing *> (
                (char *) this - offsetof (Containing, inner)
            );
        }
    } inner;
};


int main () {
    Containing c;
    std::cout
        << (c.inner.get_containing () == &c ? "success" : "fail")
        << std::endl;
}

您显示的具体代码(我在上面重复过)是可以的,因为支持 C 兼容性的 reinterpret_cast 到/从 POD 的第一个元素。

我记得 C++11 扩展了 reinterpret_cast 起作用的类型集。

但是,一旦您引入虚函数或其他非 POD'y 内容,您就超出了 offsetof 的操作机制,以及保证的 reinterpret_cast


标准语。通过使用我的 PDF 阅读器中的“查找”功能,应用于文档 [N3290.pdf](C++11 的最终草案,与标准相同),单击鼠标三下即可获得有关 offsetof< 的以下信息 被提供:

C++11 §18.2/4:
“The macro offsetof(type, member-designator) accepts a restricted set of type arguments in this International Standard. If type is not a standard-layout class (Clause 9), the results are undefined.”

同样,通过单击关于“类”的标题 9,然后让 PDF 阅读器搜索 reinterpret_cast,我发现......

C++11 9.2/20:
“A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa”


实践中。对第一个成员使用 offsetof 有点没有意义,因为它保证位于偏移量 0(之前没有填充)。为了使这件事有意义,您必须对给定代码进行一些逻辑概括,其中……

  • 相关成员不是第一个成员。
  • 指针运算是通过指向字节的指针完成的(例如 char)。

然后对于 POD 类型,或 C++11 更通用的标准布局,offsetof 没问题,但 reinterpret_cast 需要特定的编译器支持。使用 Visual C++ 就可以了。对于 g++,如果可能的话,您最好要么关闭它的愚蠢警告和相关的愚蠢优化,要么绕过 void 指针。

超出 offsetof 的限制通常不是一个好主意。例如。对于虚拟继承,偏移量可以有很大差异,不能仅从静态类型信息中推导出来。

关于c++ - 计算包含对象的this指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20773783/

相关文章:

c++ - 具有隐藏可见性的 C++ 模板参数问题

java - ParentClass.NestedClass 是否 nc= new NestedClass();隐式实例化父类实例?

pointers - 如果我想在 Rust 中安全地编码,我应该在不使用指针算法的情况下编码吗?

c++ - void* 指针的指针运算

c++ - 为什么 c++17 的 emplace() 函数没有引用资格?

c++ - ITK - 计算分段 3D 大脑 MRI 的纹理特征

c++ - 我的 std::exchange 不在命名空间 std 中?

java - 覆盖匿名类的 tostring

C# 对象组合

c - cast 周围的指针算术