在隐式转换中如何使用显式构造函数

发布于 2025-02-12 15:44:34 字数 1865 浏览 1 评论 0 原文

我正在使用列出的资源 explicit 关键字。 >在这里此帖子说:

将显式关键字在构造函数上前缀防止编译器将构造函数用于隐式转换。


现在,我编写了以下示例,该示例使用 explicit 复制constructor b :: b(const b&)在隐式转换中。示例如下: mre,带有C ++ 14和-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?

因此,我的问题是如何在上述隐式转换中使用明确的副本CTOR。我的意思是,对于我当前的理解,我期望 b p = y; 失败,就像复制初始化 b a = x; 失败。我想知道这是标准允许的,还是编译器错误。

请注意

,在我给定的演示中,使用 -fno-elide-constructors 标志。

I am learning about explicit keyword in C++ using the resources listed here and as this post says:

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


Now I wrote the following example that uses the explicit copy constructor B::B(const B&) in an implicit conversion. The example is as follows: 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

   
}

The output of the above program is:

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?

So my question is that how is it possible to use an explicit copy ctor in the above implicit conversion. I mean to my current understanding I expected B p = y; to fail just like the copy initialization B a = x; fails. I want to know is this allowed by the standard or is it a compiler bug.

Note

Note the use of -fno-elide-constructors flag in my given demo.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

待天淡蓝洁白时 2025-02-19 15:44:34

我想知道这是标准允许的,还是编译器错误。

这是良好的,由标准允许,如下所述。

可以使用 dcl.init#17.666.66.66.66.6.6.6.6.6.6.6.6.66.6.6.6.6.6.6.66.66.66.66.66.66> dcl.init .2 哪个指出:

否则(即,对于剩余的副本限制案例),用户定义的转换序列
可以从源类型转换为目标类型或(当转换功能时
如13.3.1.4所述,使用)将其列入其派生类别,最好的是
通过超负荷分辨率(13.3)选择。如果无法完成或模棱两可,
初始化是不形成的。选定的函数用初始化器表达式调用
争论;如果该函数是构造函数,则该调用初始化了CV Unqualified的临时性
目标类型的版本。临时是一个贵族。呼叫的结果(这是
然后,根据上述规则,使用构造函数的临时性来指导

是副本定性化的目的对象

(强调我的)

让我们将其应用于您的榜样。

在给定的示例中( b p = y; 源类型 a ,而目标类型为 b 。现在,使用非明确的参数化CTOR b :: B(a)使用了从源类型到目标类型的用户定义转换,此处将在此处使用。

此不明显的CTOR将以初始化器表达式作为参数调用。此外,此调用是类型 b prvalue

这里要注意的重要一件事是,此调用将用于 DirectInialize 名为 p 的对象。而且,由于在直接初始化上下文中可以使用显式CTOR,因此明确的副本可以并且将在此处使用。

效果是 as-if 我们正在写:

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

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

This is well-formed and is allowed by the standard as explained below.

The behavior of your program can be understood using dcl.init#17.6.2 which states:

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.

(emphasis mine)

Let's apply this to your example.

In the given example(B p = y; in particular) the source type is A while the destination type is B. Now there is a user-defined conversion available from the source type to the destination type using the non-explicit parameterized ctor B::B(A) which will be used here.

This non-explicit ctor will be called with the initializer expression y as its argument. Moreover, this call is a prvalue of type B.

The important thing to note here is that this call will be used to direct-initialize the object named p. And since in direct initialization context the explicit ctor can be used, therefore the explicit copy ctor can and will be used here.

The effect is as-if we're writing:

B p{/*prvalue of type B obtained from call to parameterized ctor*/};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文