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
对象?我不知道,但为什么有人要显式声明复制构造函数?预期的收益是什么?但我仍然可以使用definevoid bar(const X&a)
并像这样使用bar(X{})代码>。这不是一个隐含的副本吗?@henrikgiesel-Nopea
是一个引用,您只是将其绑定到临时的X{}
。好的,当我重写X&foo()
时,我终于明白了这一点。(当然这很愚蠢,但它帮助我理解了发生了什么)调用bar
根本不调用构造函数,它只是传递引用(指针)。您应该看到调用了无副本构造函数。
X foo(void){
X a{};
return a; // ERROR: no matching constructor found!
}