Is uniform initialization used dangerous?

I discovered a single initialization a few days ago, and I see everywhere that everyone should use it as much as possible.

However, I cannot help but think that this new syntax has more problems than it's worth ...


First example

Suppose I am writing a library in which I have such a structure:

struct MyStruct { int member0; int member1; } 

A user can write something like this using aggregate initialization:

 MyStruct myVar = {0, 1}; // member0 = 0 and member1 = 1 

Now let's say that I am updating my library and that the structure now looks like this:

 struct MyStruct { int member0; int member1; MyStruct(int p0, int p1) : member0(p1), member1(p0){} } 

Prior to C ++ 11, the user code stopped compiling, which would force the user to rewrite his code and use the constructor. But now the code will compile and be interpreted as uniform initialization:

 MyStruct myVar = {0, 1}; // member0 = 1 and member1 = 0 

Without knowing that updating his library will make his code completely different!


Second example

Now let's say that I have such a class in my library:

 class MyClass { public: MyClass(int size, int default = 0) : elements(size, default){} private: std::vector<int> elements; } 

The user can use it as follows:

 MyClass myVar (3,1); // 3 elements with value 1 

or, using a single initialization, for example:

 MyClass myVar {3,1}; // 3 elements with value 1 

Then, let’s say so, I update my library. The class now looks like this:

 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; } 

There would be no problem if the classic constructor were used:

 MyClass myVar (3,1); // 3 elements with value 1 

but the interpretation of the code will change if uniform initialization was called:

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

Based on these examples, it seems to me extremely dangerous to use a single initialization, since the interpretation of the code may change when things are added to the libraries used without any warnings.

Even worse, introducing uniform initialization makes aggregate initialization dangerous.

Did I miss something? Is there a context in which using a single initialization is safe and useful?

+6
source share
1 answer

I think that both of the problems you were dealing with have very little to do with single initialization, but illustrate the dangers of changing the interface.

You can archive the same suboptimal change in user code by updating your library as follows:

 struct MyStruct { int member1; int member0; } 

Without a single initialization. It is also possible that pre-C ++ 11 changed the constructor selected using overload resolution:

 class some_class { public: some_class(int); } 

User encoder:

 some_class var(1.0); 

If the code has been changed to:

 class some_class { public: some_class(int); some_class(double); } 

The second constructor will be called. Again, there was no uniform initialization, but the same problems arise.

So, although both examples demonstrate the fact that the meaning of user code can be changed by changing the library interface, this is not a problem caused or specific to uniform initialization, but rather a suboptimal design. This simply illustrates the fact that the library interface must be designed very carefully.

On the loop, the same initialization provides some real benefits. For them see this great answer.

+6
source

All Articles