【问题标题】:pointer to object == pointer to first member?指向对象的指针 == 指向第一个成员的指针?
【发布时间】:2011-05-17 12:33:15
【问题描述】:

为什么下面代码中的 if 条件为真?

struct A
{
    int firstMember;
} a1;

if (&a1 == static_cast<void*>(&a1.firstMember)) std::cout << "equal";

在阅读空类的Stroustrup's FAQ 时,我有点困惑,特别是下面的语句:

if (p1 == p2) cout << "nice: good optimizer";

【问题讨论】:

    标签: c++ pointers object member object-layout


    【解决方案1】:

    是的,你不能依赖它。特别是在 64 位操作系统中,编译器可能会调整地址以考虑内存对齐。

    【讨论】:

      【解决方案2】:

      引用运算符返回一个指向包含该成员的内存地址的指针。

      这里a1是一个只包含firstMember的类,所以内存中的结构就是那个元素:内存中a1的开头和firstMember的开头是一样的。

      【讨论】:

      • 这里没有引用。请参阅@Kos 的回答。
      【解决方案3】:

      引用的行为很像 C++ 中的指针。当您引用一个变量时,您是在询问该变量在内存中的位置。在这种情况下,您将 a1 中的第一条信息与 a1 本身进行比较。这是一个可行的特定情况,而不是您应该依赖的东西。

      【讨论】:

      • 这里没有引用。 &amp;a1&amp;a1.firstMember 实际上是指针。
      【解决方案4】:

      您的代码中不涉及任何引用。不要将“address-of”运算符(也称为&amp;)与引用混淆。

      您的条件返回 true,因为在这种情况下,对象恰好在内存中与其第一个(也是唯一一个)字段相同的位置开始。这就是所谓的 POD(plain-old-data)对象的情况,但并不总是如此。

      例如,如果您的类包含任何虚函数,则该条件可能为假。不要依赖它。

      【讨论】:

      • 写得好,非常简洁。 +1
      • 我唯一要补充的是,编译器可能会围绕后续成员的放置进行调整,以试图保持对象在内存中对齐。这称为填充,使这种类型的双关语更加危险,特别是因为它可能因编译器编译指示或标志而异。 Pack(1) 将在许多编译器上工作以关闭填充。不要这样做,出于一些非常好的原因,事情会被填充。除非您能阐明这些原因,以及针对您的用例的反驳论点,否则您不需要 Pack(1)。
      猜你喜欢
      • 2016-02-25
      • 1970-01-01
      • 2018-03-24
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      相关资源
      最近更新 更多