The short answer is that they kept the linker about the same, at the expense of making the compiler still more complicated than previously.
I.e., instead of this resulting in multiple definitions for the linker to sort out, it still only results in one definition, and the compiler has to sort it out.
It also leads to somewhat more complex rules for the programmer to keep sorted out as well, but it's mostly simple enough that it's not a big deal. The extra rules come in when you have two different initializers specified for a single member:
class X {
int a = 1234;
public:
X() = default;
X(int z) : a(z) {}
};
Now, the extra rules at this point deal with what value is used to initialize a
when you use the non-default constructor. The answer to that is fairly simple: if you use a constructor that doesn't specify any other value, then the 1234
would be used to initialize a
-- but if you use a constructor that specifies some other value, then the 1234
is basically ignored.
For example:
#include <iostream>
class X {
int a = 1234;
public:
X() = default;
X(int z) : a(z) {}
friend std::ostream &operator<<(std::ostream &os, X const &x) {
return os << x.a;
}
};
int main() {
X x;
X y{5678};
std::cout << x << "
" << y;
return 0;
}
Result:
1234
5678
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…