简单结构:使用非静态成员初始化,聚合初始化或构造函数的优点/缺点

时间:2016-03-10 10:04:58

标签: c++ c++11 struct

从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组合成员和聚合初始化可用,这会改变吗?)

3 个答案:

答案 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 {{},{}};