C++ 默认成员初始化和构造函数
C++ default member initialization and constructors
我想知道在哪里可以找到有关以下行为的文档:
class Foo {
public:
Foo(int argX) : Foo(argX, defaultYValue) {}
Foo(int argX, int argY) : x(argX), y(argY) {};
private:
const int x;
const int y;
const int defaultYValue = -1;
}
y 值可能未定义吗?或者标准中是否有一些文档说明它有效(我确实注意到默认成员初始化被丢弃,如果它在构造函数中被其他方式覆盖)
PS:这是在忘记默认 YValue 的静态时发现的。
是的,代码有未定义的行为。当使用 delegating constructor 时,委托构造函数将初始化 class 成员。当您将 defaultYValue
传递给委托构造函数时,它尚未初始化,因此您将未初始化的值传递给委托,并且所述委托使用该值来设置 y
.
叫出来的
The expression-list or braced-init-list in a mem-initializer is used to initialize the designated subobject (or, in the case of a delegating constructor, the complete class object) according to the initialization rules of [dcl.init] for direct-initialization.
I would like to know where I can find some documentation about the following behavior:
这称为委托,构造函数Foo::Foo(int)
称为delegating constructor。
A mem-initializer-list can delegate to another constructor of the constructor's class using any class-or-decltype that denotes the constructor's class itself. If a mem-initializer-id designates the constructor's class, it shall be the only mem-initializer; the constructor is a delegating constructor, and the constructor selected by the mem-initializer is the target constructor. The target constructor is selected by overload resolution. Once the target constructor returns, the body of the delegating constructor is executed. If a constructor delegates to itself directly or indirectly, the program is ill-formed, no diagnostic required.
Might it be possible that y value is undefined ?
是的,程序有未定义的行为。
The expression-list or braced-init-list in a mem-initializer is used to initialize the designated subobject (or, in the case of a delegating constructor, the complete class object) according to the initialization rules of [dcl.init] for direct-initialization.
这意味着目标构造函数 Foo::Foo(int, int)
用于初始化数据成员。但是由于您传递的数据成员 defaultYValue
尚未初始化,因此我们有未定义的行为。
正如您在使用 defaultYValue 时在其他答案中指出的那样,它尚未初始化。您可以通过将其设置为静态来解决此问题:
class Foo {
public:
Foo(int argX) : Foo(argX, Foo::defaultYValue) {}
Foo(int argX, int argY) : x(argX), y(argY) {};
private:
const int x;
const int y;
static const int defaultYValue = -1;
}
但是当一个构造函数就足够时,永远不要写 2 个:
class Foo {
public:
Foo(int argX, int argY = defaultYValue) : x(argX), y(argY) {};
private:
const int x;
const int y;
static const int defaultYValue = -1;
}
但真的为什么要定义一个只用过一次的常量呢?从使用中可以清楚地看出它是 y 的默认值。将其命名为 defaultYValue
:
没有获得额外的信息
class Foo {
public:
Foo(int argX, int argY = -1) : x(argX), y(argY) {};
private:
const int x;
const int y;
}
我想知道在哪里可以找到有关以下行为的文档:
class Foo {
public:
Foo(int argX) : Foo(argX, defaultYValue) {}
Foo(int argX, int argY) : x(argX), y(argY) {};
private:
const int x;
const int y;
const int defaultYValue = -1;
}
y 值可能未定义吗?或者标准中是否有一些文档说明它有效(我确实注意到默认成员初始化被丢弃,如果它在构造函数中被其他方式覆盖)
PS:这是在忘记默认 YValue 的静态时发现的。
是的,代码有未定义的行为。当使用 delegating constructor 时,委托构造函数将初始化 class 成员。当您将 defaultYValue
传递给委托构造函数时,它尚未初始化,因此您将未初始化的值传递给委托,并且所述委托使用该值来设置 y
.
The expression-list or braced-init-list in a mem-initializer is used to initialize the designated subobject (or, in the case of a delegating constructor, the complete class object) according to the initialization rules of [dcl.init] for direct-initialization.
I would like to know where I can find some documentation about the following behavior:
这称为委托,构造函数Foo::Foo(int)
称为delegating constructor。
A mem-initializer-list can delegate to another constructor of the constructor's class using any class-or-decltype that denotes the constructor's class itself. If a mem-initializer-id designates the constructor's class, it shall be the only mem-initializer; the constructor is a delegating constructor, and the constructor selected by the mem-initializer is the target constructor. The target constructor is selected by overload resolution. Once the target constructor returns, the body of the delegating constructor is executed. If a constructor delegates to itself directly or indirectly, the program is ill-formed, no diagnostic required.
Might it be possible that y value is undefined ?
是的,程序有未定义的行为。
The expression-list or braced-init-list in a mem-initializer is used to initialize the designated subobject (or, in the case of a delegating constructor, the complete class object) according to the initialization rules of [dcl.init] for direct-initialization.
这意味着目标构造函数 Foo::Foo(int, int)
用于初始化数据成员。但是由于您传递的数据成员 defaultYValue
尚未初始化,因此我们有未定义的行为。
正如您在使用 defaultYValue 时在其他答案中指出的那样,它尚未初始化。您可以通过将其设置为静态来解决此问题:
class Foo {
public:
Foo(int argX) : Foo(argX, Foo::defaultYValue) {}
Foo(int argX, int argY) : x(argX), y(argY) {};
private:
const int x;
const int y;
static const int defaultYValue = -1;
}
但是当一个构造函数就足够时,永远不要写 2 个:
class Foo {
public:
Foo(int argX, int argY = defaultYValue) : x(argX), y(argY) {};
private:
const int x;
const int y;
static const int defaultYValue = -1;
}
但真的为什么要定义一个只用过一次的常量呢?从使用中可以清楚地看出它是 y 的默认值。将其命名为 defaultYValue
:
class Foo {
public:
Foo(int argX, int argY = -1) : x(argX), y(argY) {};
private:
const int x;
const int y;
}