【问题标题】:Calculating this pointer of containing object计算包含对象的 this 指针
【发布时间】:2013-12-26 01:07:21
【问题描述】:

以下可移植且符合标准的 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;
}

【问题讨论】:

  • 好的,我删除了可能重复的问题。我唯一的问题是:“这是否符合标准?”顺便说一句,“重复问题”投票开始让 Stackoverflow 变得无用,因为投票结束的人似乎没有阅读所问的内容。
  • 我确实阅读了被问到的内容;)也就是说,我现在撤回了近距离投票,因为编辑意味着不再有真正的重叠......
  • 顺便说一句,这里有一个稍微复杂一些但失败的例子:ideone.com/2sr2JF。您需要向char * 添加一些演员表,以使这项工作更普遍(尽管有UB)。
  • 谢谢。似乎足以投射this
  • 计算“这个指针”是什么意思?你想得到 VTable 吗?为此,您可以这样做:DWORD* VTable = *reinterpret_cast&lt;DWORD**&gt;(&amp;SomeInstance);.. 再说一次,我不确定这是否是您想要的..

标签: c++ inner-classes pointer-arithmetic


【解决方案1】:
#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 to/from POD 的第一个元素。

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

但是,一旦您引入了虚拟功能或其他非 POD 的东西,您就会超出 offsetof 的运行机制,以及保证 reinterpret_cast 的运行机制。


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

C++11 §18.2/4:
“宏 offsetof(type, member-designator) 在这个 International 中接受一组受限的 type 参数 标准。如果 type 不是标准布局类(第 9 条),则结果未定义。”

同样,通过点击第 9 节关于“类”的标题,然后让 PDF 阅读器搜索 reinterpret_cast,我找到了……

C++11 9.2/20:
“一个指向标准布局结构对象的指针,使用reinterpret_cast 适当转换,指向它的 初始成员(或者如果该成员是位域,则指向它所在的单元),反之亦然”


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

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

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

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

【讨论】:

    猜你喜欢
    • 2011-05-17
    • 2013-03-14
    • 2011-11-12
    • 2021-11-06
    • 2014-01-02
    • 1970-01-01
    • 2015-08-07
    • 2015-03-05
    • 2018-06-10
    相关资源
    最近更新 更多