C++11 Isn';使用统一初始化是否危险?

C++11 Isn';使用统一初始化是否危险?,c++11,uniform-initialization,list-initialization,C++11,Uniform Initialization,List Initialization,几天前我发现了统一初始化,我发现到处都应该尽可能多地使用它 然而,我忍不住认为这种新语法比它的价值更麻烦 第一个示例 假设我写了一个库,其中有这样一个结构: struct MyStruct { int member0; int member1; } struct MyStruct { int member1; int member0; } 用户可以使用聚合初始化编写如下内容: MyStruct myVar = {0, 1}; // member0 = 0 a

几天前我发现了统一初始化,我发现到处都应该尽可能多地使用它

然而,我忍不住认为这种新语法比它的价值更麻烦


第一个示例

假设我写了一个库,其中有这样一个结构:

struct MyStruct
{
    int member0;
    int member1;
}
struct MyStruct
{
    int member1;
    int member0;
}
用户可以使用聚合初始化编写如下内容:

MyStruct myVar = {0, 1}; // member0 = 0 and member1 = 1
MyStruct myVar = {0, 1}; // member0 = 1 and member1 = 0
现在,让我们假设我更新了我的库,结构现在如下所示:

struct MyStruct
{
    int member0;
    int member1;

    MyStruct(int p0, int p1) : member0(p1), member1(p0){}
}
MyClass myVar (3,1);  // 3 elements with value 1
MyClass myVar {3,1};  // 3 elements with value 1
class MyClass
{
public:
    MyClass(int size, int default = 0) : elements(size, default){}
    MyClass(std::initializer_list<int> elts) : elements(elts){}
private:
    std::vector<int> elements;
}
在C++11之前,用户代码将停止编译,这将迫使用户重写代码并使用构造函数。但现在,代码将编译并解释为统一初始化:

MyStruct myVar = {0, 1}; // member0 = 0 and member1 = 1
MyStruct myVar = {0, 1}; // member0 = 1 and member1 = 0
在用户不知道的情况下,更新他的库将使他的代码做一些非常不同的事情


第二个示例

现在,让我们假设我的库中有这样一个类:

class MyClass
{
public:
    MyClass(int size, int default = 0) : elements(size, default){}
private:
    std::vector<int> elements;
}
或者,使用统一初始化,如下所示:

struct MyStruct
{
    int member0;
    int member1;

    MyStruct(int p0, int p1) : member0(p1), member1(p0){}
}
MyClass myVar (3,1);  // 3 elements with value 1
MyClass myVar {3,1};  // 3 elements with value 1
class MyClass
{
public:
    MyClass(int size, int default = 0) : elements(size, default){}
    MyClass(std::initializer_list<int> elts) : elements(elts){}
private:
    std::vector<int> elements;
}
再说一次,让我们说我更新了我的库。该类现在如下所示:

struct MyStruct
{
    int member0;
    int member1;

    MyStruct(int p0, int p1) : member0(p1), member1(p0){}
}
MyClass myVar (3,1);  // 3 elements with value 1
MyClass myVar {3,1};  // 3 elements with value 1
class MyClass
{
public:
    MyClass(int size, int default = 0) : elements(size, default){}
    MyClass(std::initializer_list<int> elts) : elements(elts){}
private:
    std::vector<int> elements;
}
但如果调用统一初始化,代码解释将发生变化:

MyClass myVar {3,1};  // 2 elements with values 3 and 1

基于这些示例,在我看来,用户使用统一初始化是非常危险的,因为在没有任何警告的情况下,当向使用过的库中添加内容时,代码解释可能会发生更改

更糟糕的是,统一初始化的引入使聚合初始化变得危险


我错过什么了吗?是否存在使用统一初始化既安全又有用的环境?

我认为您提到的这两个问题与统一初始化本身关系不大,但说明了更改接口的危险性

您可以通过如下方式更新库来归档用户代码中的次优更改:

struct MyStruct
{
    int member0;
    int member1;
}
struct MyStruct
{
    int member1;
    int member0;
}
不涉及统一初始化。在c++11之前,也可以更改通过重载解析选择的构造函数:

class some_class
{
    public:
    some_class(int);
}
用户编码员:

some_class var(1.0);
如果代码更改为:

class some_class
{
    public:
    some_class(int);
    some_class(double);
}
将调用第二个构造函数。同样,没有涉及统一的初始化,但同样的问题也会发生

因此,虽然这两个示例都展示了这样一个事实,即用户代码的含义可以通过更改库接口来更改,但这不是一个由统一初始化引起或特定于统一初始化的问题,而是一个次优设计。它仅仅说明了一个事实,即库接口的设计应该非常仔细


相反,统一初始化提供了一些真正的优势。对于这些,请参见这一点,这是非常有趣的。对于第二种情况,两种情况下的语法相似,但仍然存在差异。但对于第一种情况,这看起来非常麻烦。我认为,无论是否涉及统一初始化,更改接口都是危险的。你确实有道理。但我想这意味着纯粹主义者不会太多地使用统一初始化……纯粹主义者通常不会使用任何东西,因为这很危险。他们不设计接口,因为他们可以改变,等等。。。