从C ++ 11开始,似乎有三种可行的方法来定义简单的结构。 (我知道在C ++ 14中可以组合选项A和B,但我的问题与C ++ 11有关。)
// non-static member initialization
struct PointA
{
double x = 0.0;
double y = 0.0;
};
PointA pA1;
PointA pA2; pA2.x = 2.0; pA2.y = -1.0; // can this be made more elegantly ?
// aggregate initialization
struct PointB
{
double x;
double y;
};
PointB pB1 = { 0.0, 0.0 }; // or does it suffice to write PointB pB1; here?
PointB pB2 = { 2.0, -1.0 };
// constructor
struct PointC
{
double x;
double y;
PointC(double initX = 0.0, double initY = 0.0) : x(initX), y(initY) { }
};
PointC pC1;
PointC pC2( 2.0, -1.0 );
使用它们的优点/缺点是什么?在C ++ 11中哪些情况应该首选? (如果C ++ 14组合成员和聚合初始化可用,这会改变吗?)
答案 0 :(得分:1)
构造函数的工作是建立用户定义的类不变量。
如果没有用户定义的类不变量,那么构造函数的工作就是确保所有数据成员都有有效值,即不是不确定(这样的值可能会导致未定义使用时的行为)。
当唯一的类不变量是“数据成员具有有效值”,即辅助作业时,那么只需要一个构造函数作为使该类具有白痴性的方法,以便新手不能使用它来声明未初始化变量。但这有使非POD课程的成本。这些问题必须平衡,但值得注意的是,您始终可以定义POD类以及具有构造函数的派生类。
关于第一个代码示例,
struct Point
{
double x = 0.0;
double y = 0.0;
};
Point a1;
Point a2; a2.x = 2.0; a2.y = -1.0; // can this be made more elegantly ?
由于数据成员初始值设定项,此类有效地具有如下构造函数:
Point::Point()
: x( 0.0 ), y( 0.0 )
{}
这可以防止使用Visual C ++ 2015编译类似
的声明Point point = { 5.0, 6.0 };
MinGW g ++ 5.1.0接受该声明。我不知道这是正式的。但是作为实际编程的问题,不同的编译器行为意味着 当前在您的示例中没有更优雅的方式来执行a2
的注释声明。
关于第二个代码示例,
// aggregate initialization
struct Point
{
double x;
double y;
};
Point b1 = { 0.0, 0.0 }; // or does it suffice to write PointB pB1; here?
Point b2 = { 2.0, -1.0 };
仅仅编写Point b1;
是否足够取决于:
如果这是一个命名空间范围声明,那么b1
首先是零初始化的,所以它没关系。
如果这是一个本地声明,那么就没有自动零初始化,因此省略显式初始化将为您提供不确定的值,从而导致UB。
但是,您可以将声明减少为
Point b1 = {};
或
Point b1{};
取决于您的一般惯例。
答案 1 :(得分:1)
在c ++ 14中,我更喜欢
struct PointA
{
double x = 0.0;
double y = 0.0;
};
允许
PointA pA1; // {0., 0.}
PointA pA2 = { 2.0, -1.0 };
但也
PointA pA3 = { 2.0 }; // {2., 0.}
这可能是不受欢迎的。
在c ++ 11中(或者如果你想禁止一些构造函数):
struct PointD
{
PointD() : PointD(0, 0) {}
PointD(double x, double y) : x(x), y(y) {}
double x;
double y;
};
答案 2 :(得分:0)
您可以依赖默认构造函数。
您可以简化您定义的任何构造函数。
不能写PointB pB1是不够的。但你可以放 PointB pB1 {{},{}};