initialization - 是否应该忽略显式复制构造函数?

标签 initialization c++14 explicit

这是一个小例子,演示了一个不清楚的时刻

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 type T using a static_cast of the form static_cast<T>(e) if the declaration T t(e); is well-formed, for some invented temporary variable t (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/

相关文章:

java - 构造函数出现问题 : Natural Number using Stack<Integer>

c++ - 模板特化 : ‘Scalar’ does not name a type

c# - 因非对象字段错误而错误对齐或重叠

c++11 - C++11 的显式关键字和多参数构造函数

初始化实例变量的Pythonic方式

php - PHP 是否有一种工具可以减少类和构造函数中参数声明和初始化的重复?

c++ - 初始化聚合基础(GCC 和 clang 不同意)

c++ - 用于显示文件许可的API

java - 编程语言中的 "Explicitly"和 "Implicitly"有什么区别?

java - 父类(super class)类初始化之前的子类最终静态初始化?