Whi*_*TiM 17 c++ explicit language-lawyer c++14 c++17
考虑以下代码:
struct X{
explicit X(){}
explicit X(const X&){}
};
void foo(X a = X()){}
int main(){}
Run Code Online (Sandbox Code Playgroud)
使用C++ 14标准,GCC 7.1和clang 4.0都拒绝代码,这正是我所期望的.
但是,使用C++ 17(-std=c++1z),它们都接受代码.什么规则变了?
对于两个编译器都表现出同样的行为,我怀疑这是一个bug.但据我所知,最新的草案仍然说,默认参数使用复制初始化 1的语义.同样,我们知道explicit构造函数只允许直接初始化 2.
son*_*yao 11
因为复制省略的行为改变了C++ 17; 对于这种情况,优化是强制性的.
在下列情况下,编译器需要省略类对象的复制和移动构造函数,即使复制/移动构造函数和析构函数具有可观察的副作用:
在初始化中,如果初始化表达式是prvalue且源类型的cv-nonqualified版本与目标类相同,则初始化表达式用于初始化目标对象:
Run Code Online (Sandbox Code Playgroud)T x = T(T(T())); // only one call to default constructor of T, to initialize x
并用于复制初始化:
复制初始化的效果是:
首先,如果
T是一个类类型,并且初始化程序是一个prvalue表达式,其cv-unqualified类型与它是同一个类T,则初始化程序表达式本身,而不是从中实现的临时表达式,用于初始化目标对象:请参阅copy elision(自C++ 17)如果
T是类类型并且其他类型的cv-nonqualified版本是T派生自的类T,T则检查非显式构造函数 并通过重载决策选择最佳匹配.然后调用构造函数来初始化对象.
这意味着X a = X(),a将直接默认构造,复制/移动构造函数及其副作用将完全被忽略.不会发生用于重载解析的非显式构造函数的选择,这在C++ 14(以及之前)中是必需的.对于这些保证的情况,复制/移动构造函数不参与,那么无论它们是否存在都无关紧要explicit.
| 归档时间: |
|
| 查看次数: |
635 次 |
| 最近记录: |