为什么我们不能在声明时初始化类成员?

2021-12-30 00:00:00 class initialization constructor c++ member

我想知道为什么我们不能在成员声明时初始化成员.

I wonder if there is a reason why we can't initialize members at their declaration.

class Foo
{
    int Bar = 42; // this is invalid
};

相当于使用构造函数初始化列表.

As an equivalent of using constructor initialization lists.

class Foo
{
    int Bar;
public:
    Foo() : Bar(42) {}
}

我个人的理解是,上面的例子更具表现力和意图.此外,这是一个较短的语法.而且我没有看到任何与其他语言元素混淆的可能性.

My personal understanding is that the above example is much more expressive and intentional. Moreover this is a shorter syntax. And I don't see any possibility of confusion with other language elements.

官方对此有澄清吗?

推荐答案

在 C++11 之前,不能像这样初始化非静态成员.如果您使用 C++11 编译器进行编译,它应该很乐意接受您提供的代码.

The initialization of non-static members could not be done like this prior to C++11. If you compile with a C++11 compiler, it should happily accept the code you have given.

我想首先不允许它的原因是因为数据成员声明不是定义.没有对象被引入.如果您有一个数据成员,例如 int x;,则在您实际创建类类型的对象之前,不会创建 int 对象.因此,此成员上的初始化程序会产生误导.只有在构造过程中才能给成员赋值,这正是成员初始化列表的作用.

I imagine that the reason for not allowing it in the first place is because a data member declaration is not a definition. There is no object being introduced. If you have a data member such as int x;, no int object is created until you actually create an object of the type of the class. Therefore, an initializer on this member would be misleading. It is only during construction that a value can be assigned to the member, which is precisely what member initialization lists are for.

在添加非静态成员初始化之前,还有一些技术问题需要解决.考虑以下示例:

There were also some technical issues to iron out before non-static member initialization could be added. Consider the following examples:

struct S {
    int i(x);
    // ...
    static int x;
};

struct T {
    int i(x);
    // ...
    typedef int x;
};

当解析这些结构体时,在解析成员i时,是数据成员声明(如S)还是一个不明确的成员函数声明(如T).

When these structs are being parsed, at the time of parsing the member i, it is ambiguous whether it is a data member declaration (as in S) or a member function declaration (as in T).

使用添加的功能,这不是问题,因为您无法使用此括号语法初始化成员.您必须使用 brace-or-equal-initializer 如:

With the added functionality, this is not a problem because you cannot initialize a member with this parantheses syntax. You must use a brace-or-equal-initializer such as:

int i = x;
int i{x};

这些只能是数据成员,所以我们没有问题了.

These can only be data members and so we have no problem any more.

请参阅提案 N2628 以获得更全面的了解在提出非静态成员初始值设定项时必须考虑的问题.

See the proposal N2628 for a more thorough look at the issues that had to be considered when proposing non-static member initializers.

相关文章