The Future of Non-Static Data Member Initialization

In Visual Studio 2013 we shipped an implementation of non-static data member initialization (hereby referred to as “NSDMI”), which is a feature that allows code such as the following:

class C { int n = 42; };

Here, n is a non-static member of the class, and it is initialized directly in its declaration, and not via a constructor.

Unfortunately, the code in our compiler (some of it written 30 years ago) for handling initialization suffers from many longstanding architectural limitations. This code was sufficient for C++03-style initialization, but NSDMI, a C++11 feature, caused it to exhibit these limitations as severe bugs. One of these bugs is described in the MSDN article about error C2797. List initialization inside a non-static data member initializer would have been silently converted into a function call, resulting in incorrect behavior. That is, if one writes:

#include <vector>

class S std::vector<int> v{ 1, 2 }; };

The compiler would have treated the code above as if the user had written:

#include <vector>

class S std::vector<int> v = std::vector<int>(1, 2); };

Instead of initializing the vector with two given elements, the Visual Studio 2013 RTM compiler initializes it with length one and a single element. We’ve received countless bug reports about this behavior in the past year. Furthermore, this is not the only issue that prevents initializer lists from functioning correctly.

We originally planned to fix this bug in an update to Visual Studio 2013, but from an engineering perspective, the right thing to do is to avoid another kludge and thoroughly address the handling of initialization. But overhauling compiler architecture is a massive task due to the amount of fundamental code that needs to be modified. We could not risk creating incompatibilities or large bug tails in an update, so a correct implementation of NSDMI could only be shipped in a major release.

Meanwhile, we still needed to address the steady stream of incoming feedback about bad code generation, so we made the hard decision of creating error C2797. This error guides users towards avoiding the issue and working around it by writing explicit constructions of inner lists, as the MSDN article suggests. The following code, for example, works as expected:

#include <vector>

class S std::vector<int> v = std::vector<int> {1, 2}; };

We are aware that the release notes for Visual Studio 2013 Update 3 did not include a notification about this new error. That was a mistake and we sincerely apologize for any confusion this has caused. However, C2797 will continue to be present in all future versions of Visual Studio 2013, so we recommend that you immediately make use of the provided workarounds. The architectural changes and fixes for initialization will be included in Visual Studio “14” RTM.