这是一个小例子,演示了一个不清楚的时刻
struct CL
{
CL(){}
CL(int){}
explicit CL(const CL&){}
};
int main() {
CL cl1;
CL cl2=5; //(1)
CL cl3=(CL)5; //(2)
return 0;
}
CL 类具有来自 int 的转换构造函数和标记为显式的复制构造函数。在 (1) 中,情况 5 (int) 隐式转换为 CL,然后直接初始化 cl2。在 (2) 情况下,cl3 是复制初始化的。在这两种情况下都必须涉及显式的复制构造函数。但不同的编译器给出不同的结果:
clang 和 VS:第一种情况是正确的,但第二种情况是错误的
gcc:两种情况都是错误的
我认为 clang 和 VS 是正确的,因为根据标准“显式”关键字可以防止在复制初始化中使用构造函数,但不能在直接初始化中使用构造函数,并且 gcc 是错误的,因为直接初始化适用于 (1) 情况.
哪个编译器是正确的?
最佳答案
§ 12.3.1 [class.conv.ctor]/p2:
An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax (8.5) or where casts (5.2.9, 5.4) are explicitly used.
示例1:
CL cl2 = 5;
§ 8.5 [dcl.init]/p17:
The function selected is called with the initializer expression as its argument; if the function is a constructor, the call initializes a temporary of the cv-unqualified version of the destination type. The temporary is a prvalue. The result of the call (which is the temporary for the constructor case) is then used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization.
在直接初始化中,explicit
可以考虑构造函数,因此不会出现错误。 GCC trunk 已经编译了这个例子 successfully 。这是bug 54521 。
示例2:
CL cl3 = (CL)5;
在这种情况下,该转换语法执行 static_cast
:
§ 5.2.9 [expr.static.cast]/p4:
An expression
e
can be explicitly converted to a typeT
using astatic_cast
of the formstatic_cast<T>(e)
if the declarationT t(e);
is well-formed, for some invented temporary variablet
(8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion.
rhs 的类型为 CL
,并且(复制)初始化需要非 explicit
构造函数,因此错误是预料之中的。
关于initialization - 是否应该忽略显式复制构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32427433/