C++ 我怎么能';t使用显式构造函数构造返回类型

C++ 我怎么能';t使用显式构造函数构造返回类型,c++,constructor,explicit,C++,Constructor,Explicit,我研究了显式构造函数及其行为,因此创建了这个类: #include <iostream> class X { public: explicit X(void) { std::cout << "Default constructor\n"; } explicit X(X const& x) { std::cout << "Copy constructor\n"; }

我研究了显式构造函数及其行为,因此创建了这个类:

#include <iostream>

class X
{
public:
    explicit X(void)
    {
        std::cout << "Default constructor\n";
    }
    explicit X(X const& x)
    {
        std::cout << "Copy constructor\n";
    }
    explicit X(X&& x)
    {
        std::cout << "Move constructor\n";
    }
};
如您所见,我无法在
foo()中返回
a
。我知道它试图用copy构造函数初始化返回类型
Foo
,但由于某种原因它无法使用它

为什么它不能使用我提供的复制构造函数?我知道
显式
规范会导致问题,因为当我从复制构造函数中删除它时,它会工作。但是为什么呢

更让我困惑的是,我可以做到以下几点:

void bar(const X& a) { /* */ }
bar(X{});

它没有抱怨。但是
bar()
不应该像
foo()
构造它的返回类型那样构造它的参数
a
吗?

你不能,因为你说你不希望编译器在声明它显式时隐式地使用它

explicit X(X const& x)
但是必须将
x
复制到返回值中。把它改成

X(X const& x)
一切都会好起来的


当您从
foo
返回时:

X foo()
{
    X a{};
    return a;
}
您正在将
a
隐式复制到
foo
的返回中。但是复制构造函数被标记为显式的,所以这是不允许的


我不确定是否有理由将复制/移动构造函数标记为显式的

我想你误解了
显式
的含义。
显式
构造函数将不用于隐式类型转换/强制转换。这意味着

X foo(void){
    X a{};
    return a;  // ERROR: no matching constructor found!
}
不会编译,因为您已经告诉编译器不要隐式使用复制构造函数


我认为你想要实现的是“移动”而不是复制
a
。只要类中有一个(正常的)移动构造函数,
a
将被移动而不是复制,这是默认行为。实际上,即使使用c++99,大多数编译器都足够聪明,可以优化这个副本

“我知道显式规范导致了这个问题,因为当我从复制构造函数中删除它时,它可以工作。但是为什么?”-OP。这意味着,我无法让
foo()
返回一个完整的
foo
对象?我不知道,但为什么有人要显式声明复制构造函数?预期的收益是什么?但我仍然可以使用define
void bar(const X&a)
并像这样使用
bar(X{})。这不是一个隐含的副本吗?@henrikgiesel-Nope
a
是一个引用,您只是将其绑定到临时的
X{}
。好的,当我重写
X&foo()
时,我终于明白了这一点。(当然这很愚蠢,但它帮助我理解了发生了什么)调用
bar
根本不调用构造函数,它只是传递引用(指针)。您应该看到调用了无副本构造函数。
X foo(void){
    X a{};
    return a;  // ERROR: no matching constructor found!
}