是否必须初始化成员才能使用其地址?

Ayx*_*xan 23 c++ pointers initialization language-lawyer

可以在初始化数据成员之前初始化指向该数据成员的指针吗?换句话说,这是有效的C ++吗?

#include <string>

class Klass {
public:
    Klass()
        : ptr_str{&str}
        , str{}
    {}
private:
    std::string *ptr_str;
    std::string str;
};
Run Code Online (Sandbox Code Playgroud)

这个问题与我的相似,但顺序在那里正确,答案说

我建议不要像这样编码,以防有人更改您班上成员的顺序。

这似乎意味着撤销顺序是非法的,但是我不确定。

eer*_*ika 26

是否必须初始化成员才能使用其地址?

没有。

可以在初始化数据成员之前初始化指向该数据成员的指针吗?换句话说,这是有效的C ++吗?

是。是。

没有限制一元&的操作数需要初始化。标准中的一元和运算符规范中有一个示例:

int a;
int* p1 = &a;
Run Code Online (Sandbox Code Playgroud)

在这里,的值a未初始化,可以指向它。

该示例未演示的是在对象的生存期开始之前指向它,这就是您的示例中发生的情况。如果已占用存储空间,则明确允许在其生存期之前和之后使用指向该对象的指针。标准草案说:

[basic.life]在对象的生存期开始之前但已分配了该对象将占用的存储空间之后,或者在对象的生存期结束之后以及该对象占用的存储空间被重用或释放之前,任何指针表示对象将要或曾经位于的存储位置的地址可以使用,但只能以有限的方式使用...

规则继续列出如何限制使用。您可以按常识相处。简而言之,您可以像对待一样对待它void*,除非违反这些限制是UB而不是格式错误。存在类似的规则可供参考。

特别是在计算非静态成员的地址方面也有限制。标准草案说:

[class.cdtor] ...要形成一个指向对象的直接非静态成员的指针(或访问该对象的直接非静态成员的值)obj,的构造obj必须已经开始并且其破坏还没有完成,否则,该指针的计算值(或访问成员值)会导致未定义的行为。

在的构造函数中Klass,的构建Klass已经开始,破坏还没有完成,因此可以满足上述规则。


PS您的班级是可复制的,但是副本将具有指向另一个实例成员的指针。考虑一下这是否对您的课堂有意义。如果没有,则需要实现自定义复制并移动构造函数和赋值运算符。像这样的自引用很少见,在这种情况下,您可能需要针对它们的自定义定义,但不需要自定义析构函数,因此这是五个(或三个)规则的例外。

PPS如果您打算指向成员之一,而没有成员指向任何对象,那么您可能想使用指向成员的指针而不是指向对象的指针。

  • 引用本标准的相关部分会很高兴。这些可能是相关的:http://eel.is/c++draft/basic.life#6.sentence-1和http://eel.is/c++draft/class.cdtor#3.sentence-2 。 (7认同)