C++标准(第8.5节)说:
如果程序要求对const限定类型T的对象进行默认初始化,则T应为具有用户提供的默认构造函数的类类型.
为什么?在这种情况下,我无法想到为什么需要用户提供的构造函数.
struct B{
B():x(42){}
int doSomeStuff() const{return x;}
int x;
};
struct A{
A(){}//other than "because the standard says so", why is this line required?
B b;//not required for this example, just to illustrate
//how this situation isn't totally useless
};
int main(){
const A a;
}
Run Code Online (Sandbox Code Playgroud) 首先,我有一个结构,其中一个值具有默认值
struct S {
int a = 1;
};
Run Code Online (Sandbox Code Playgroud)
当gcc和clang都是非const/non-constexpr时,可以默认构造此类型.在两者之下,std::is_pod<S>::value是false.奇怪的行为如下:
S s1; // works under both
const S s2{}; // works under both
const S s3; // only works in gcc, clang wants a user-provided constructor
Run Code Online (Sandbox Code Playgroud)
以下尝试都没有对clang产生影响:
struct S {
int a = 1;
constexpr S() = default; // defaulted ctor
virtual void f() { } // virtual function, not an aggregate
private:
int b = 2; // private member, really not an aggregate
};
Run Code Online (Sandbox Code Playgroud)
我唯一可以做的就是 …
该锵文档整齐地解释说,
如果类或结构没有用户定义的默认构造函数,C++不允许您默认构造它的const实例([dcl.init],p9)
基本原理是如果const对象未正确初始化,则以后不能更改.以下代码仅具有用户声明的默认构造函数Test,但其所有成员都具有类内初始值设定项,
#include<iostream>
class Test
{
public:
Test() = default;
void print() const { std::cout << i << "\n"; }
private:
int i = 42; // will propagate to the default constructor!
};
int main()
{
Test const t; // <-- Clang chokes on the const keyword, g++ does not
t.print(); // prints 42
}
Run Code Online (Sandbox Code Playgroud)
所以用户提供默认构造函数的基本原理对我来说似乎是多余的.事实上,g ++ 4.8.1确实可以毫无问题地编译它(在线示例),尽管Clang <= 3.2没有.
问题:为什么完整的类内initalizers +用户声明的默认构造函数的组合不足以默认构造一个const对象?是否有针对C++ 14标准的修复程序?
更新:任何人都可以尝试使用Clang 3.3/3.4,看看与Clang …
考虑以下示例:
#include <iostream>
#include <type_traits>
struct A
{
//A() = default; // does neither compile with, nor without this line
//A(){}; // does compile with this line
int someVal{ 123 };
void foobar( int )
{
};
};
int main()
{
const A a;
std::cout << "isPOD = " << std::is_pod<A>::value << std::endl;
std::cout << "a.someVal = " <<a.someVal << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这可以用g ++编译,但不能用clang ++编译,尝试使用以下命令: clang++ -std=c++11 -O0 main.cpp && ./a.out
从clang编译错误:
main.cpp:19:13:错误:const类型'const A'对象的默认初始化需要用户提供的默认构造函数
我从这个Stack Overflow问题中了解到,非POD类获得默认构造函数.这甚至不是必需的,因为变量具有c ++ …
例如,clang不编译此代码,因为struct A下面的默认默认构造函数A() = default;不被视为用户提供.
struct A{ A() = default; };
const A a;
Run Code Online (Sandbox Code Playgroud)
但如果你看[dcl.fct.def.general]/1,你会看到:
function-body:
ctor-initializer opt compound-statement
function-try-block
= default ;
= delete ;
也就是说,= default;是函数体的默认构造函数A::A(),这是相同的话说,定义A() = default;上述相当于A(){}为{}是身体的默认构造函数.
顺便说一句,g++汇编上面的片段,但我知道g++在这方面还有其他问题,根据Jonathan Wakely的评论.