c++ - 显式构造函数如何用于隐式转换

标签 c++ c++14 language-lawyer explicit

我正在了解 explicit使用列出的资源的 C++ 中的关键字 here以及 this post说:

Prefixing the explicit keyword to the constructor prevents the compiler from using that constructor for implicit conversions.


现在我编写了以下使用 explicit 的示例复制构造函数B::B(const B&)在隐式转换中。示例如下:MRE with C++14 and -fno-elide-constructors flag

struct A {
    A()
    {
    std::cout<<"A's default ctor called"<<std::endl;
    }
    A(const A&)
    {
        std::cout<<"A's copy ctor called"<<std::endl;
    }
};
class B
{
public:
    B()
    {
        std::cout<<"B default ctor called"<<std::endl;
    }
    B(A)
    {
        std::cout<<"B's parametrized ctor called"<<std::endl;
    }
    explicit B(const B&)
    {
        std::cout<<"explicit B copy ctor called"<<std::endl;
    }
};



int main()
{
    B x;
    //B a = x; //this fails AS EXPECTED

    A y;

    B p = y; //Why doesn't this fail as well? This uses the copy ctor in addition to the param ctor. How the explicit copy ctor is used here in implicit conversion

   
}

上述程序的输出为:

B default ctor called
A's default ctor called
A's copy ctor called
B's parametrized ctor called
explicit B copy ctor called   <--------------HOW IS THAT EXPLICIT CTOR IS USED HERE IN IMPLICIT CONVERSION?

所以我的问题是如何在上面的隐式转换中使用显式复制 vector 。我的意思是,根据我目前的理解,我期望 B p = y;就像复制初始化 B a = x; 一样失败失败。我想知道这是标准允许的还是编译器错误。

注意

注意 -fno-elide-constructors 的使用在我给定的演示中标记。

最佳答案

I want to know is this allowed by the standard or is it a compiler bug.

这是格式良好的,并且是标准所允许的,如下所述。

可以使用 dcl.init#17.6.2 来理解程序的行为其中指出:

Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 13.3.1.4, and the best one is chosen through overload resolution (13.3). If the conversion cannot be done or is ambiguous, the initialization is ill-formed. 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.

(强调我的)

让我们将其应用到您的示例中。

在给定的示例中(特别是 B p = y;),源类型A而目标类型为B 。现在,可以使用非显式参数化构造函数 B::B(A) 从源类型到目标类型进行用户定义的转换。此处将使用它。

这个非显式构造函数将使用初始化表达式 y 进行调用。作为其论点。此外,此调用是 B 类型的纯右值 .

这里要注意的重要一点是,此调用将用于直接初始化名为 p 的对象。并且由于在直接初始化上下文中可以使用显式构造函数,因此可以并且将在此处使用显式复制构造函数。

效果就好像我们正在编写:

B p{/*prvalue of type B obtained from call to parameterized ctor*/};

关于c++ - 显式构造函数如何用于隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72857056/

相关文章:

c# - 在 windows 中使用 linux 根库

c++ - 使用数据文件排序计算时遇到问题

c++ - std::map 的类型要求

css - 在CSS Flexbox中,为什么没有“justify-items”和“justify-self”属性?

c++ - C++ 中的结构偏移量和指针安全

c++ - type_traits 中是否有类似 std::remove_const_reference 的东西

java - 痛饮+Java : namespaces and packages

c++ - 如何绕过成员函数末尾对析构函数的调用?

C++反向整数序列实现

c++ - 为什么 C++11 move 运算符 (=) 的行为不同