为什么在对象初始化期间,此指针指向成员构造函数中的错误对象?

Why does this pointer points to wrong object inside member's constructor during object initialization?

提问人:Yusuf Tarık Günaydın 提问时间:3/9/2021 更新时间:3/9/2021 访问量:63

问:

以下代码将同一地址打印两次:

#include <iostream>

struct B
{
    B()
    {
        std::cout << this << std::endl;
    }
};

struct A
{
    A()
    {
        std::cout << this << std::endl;
    }
    
    B b;
};

int main()
{
    A a;
}

为什么此指针指向 B 构造函数中的 A?

C++ 指针 构造函数 this

评论

1赞 Roy Avidan 3/9/2021
因为它们在同一个空间里。A 首先包含一个 B 字段(并且仅在这种情况下),因此他的空间中的第一个对象是 B 对象。指针是相同的,因为 A 对象和 B 字段在内存中共享相同的空间。

答:

2赞 Serge Ballesta 3/9/2021 #1

B 是一个空类,因此它是一个标准布局类。

A 只包含一个(非静态)成员,即 B。它没有虚拟方法。因此,它也是一个标准的布局类。

对于标准布局类,标准要求对象的地址与其第一个子对象的地址相同。

因此,您看到相同的地址是正常的,并且 A 对象及其 B 子对象是指针可互换的。


小心接下来是原来的错误答案。它仅供参考,但完全是错误的 它只是一个实现细节。第一个子对象保证仅在标准布局类中具有与其包含对象相同的地址,而 A 和 B 都不是。

在这里,您的实现选择为两个对象提供相同的地址,但另一个实现可能使用不同的地址。

永远不要依赖实现细节......

评论

0赞 Caleth 3/9/2021
B是空的,即 StandardLayout,并且只包含一个空的非静态数据成员,所以它也是A
0赞 Serge Ballesta 3/9/2021
@Caleth:你是对的,我错了。A 有一个非平凡的构造函数,不是一个平凡的类,但它没有虚拟方法,确实是标准布局。我把这两个概念混为一谈,给出了一个错误的答案。
0赞 Caleth 3/9/2021
不用担心:)它们是非常相似的概念
0赞 Caleth 3/9/2021 #2

这两个指针具有相同的值,但它们指向不同的对象。对象有一个对象,它是BAA

这是由标准保证的,因为它们是 StandardLayoutType

  • 所有非静态数据成员都具有相同的访问控制
    • 真空真实B
    • True forA
  • 没有虚拟函数或虚拟基类
    • 对两者都为 True 和AB
  • 没有引用类型的非静态数据成员
    • 对两者都为 True 和AB
  • 所有非静态数据成员和基类本身都是标准布局类型
    • 真空真实B
    • True forA
  • 没有两个(可能是间接的)相同类型的基类子对象
    • 真空地为 和AB
  • 在同一类中声明所有非静态数据成员和位字段(全部在派生中或全部在某个基中)
    • 真空真实B
    • True forA
  • 没有一个基类子对象具有与 [复杂条件] 相同的类型
    • 真空地为 和AB