为什么我不能使用显式构造函数来构造 return 类型
How come I can't use explicit constructor for constructing a return type
我玩弄了显式构造函数及其行为,所以我创建了这个 class:
#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";
}
};
这基本上只是测试显式构造函数的存根。
然后我想尝试几种情况。所以我尝试了这个:
X foo(void)
{
X a{};
return a; // ERROR: no matching constructor found!
}
int main()
{
X w{}; // Default Constructor
X x{w}; // Copy Constructor
X y{std::move(x)}; // Move Constructor
X z{foo()};
}
如您所见,我无法在 foo()
中 return a
。我知道它试图用复制构造函数初始化 return 类型 Foo
,但由于某种原因它不能使用它。
为什么它不能使用我提供的拷贝构造函数?我知道 explicit
规范会导致问题,因为当我将它从复制构造函数中删除时它会起作用。但是为什么?
更让我困惑的是,我可以做到以下几点:
void bar(const X& a) { /* */ }
bar(X{});
它没有抱怨。但是 bar()
不应该像 foo()
构造它的 return 类型一样构造它的参数 a
吗?
你不能,因为你说过你不希望编译器在你显式声明它时隐式使用它。
explicit X(X const& x)
但是 x
必须复制到 return 值中。只需将其更改为
X(X const& x)
一切正常。
当您 return 来自 foo
:
X foo()
{
X a{};
return a;
}
您正在将 a
隐式复制到 foo
的 return 中。但是复制构造函数被标记为 explicit
,所以这是不允许的。
我不确定是否有理由标记 copy/move 构造函数 explicit
。
我想你误解了explicit
的意思。 explicit
构造函数将不会用于隐式类型 CONVERSIONS/CASTS。这意味着
X foo(void){
X a{};
return a; // ERROR: no matching constructor found!
}
不会编译,因为您已经告诉编译器不要隐式使用复制构造函数。
我估计你要实现的是"move"而不是复制a
。只要 class 中有一个(正常的)移动构造函数,a
就会被移动而不是被复制——这是默认行为。实际上,即使使用 c++99,大多数编译器也足够聪明,可以优化这个副本。
我玩弄了显式构造函数及其行为,所以我创建了这个 class:
#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";
}
};
这基本上只是测试显式构造函数的存根。 然后我想尝试几种情况。所以我尝试了这个:
X foo(void)
{
X a{};
return a; // ERROR: no matching constructor found!
}
int main()
{
X w{}; // Default Constructor
X x{w}; // Copy Constructor
X y{std::move(x)}; // Move Constructor
X z{foo()};
}
如您所见,我无法在 foo()
中 return a
。我知道它试图用复制构造函数初始化 return 类型 Foo
,但由于某种原因它不能使用它。
为什么它不能使用我提供的拷贝构造函数?我知道 explicit
规范会导致问题,因为当我将它从复制构造函数中删除时它会起作用。但是为什么?
更让我困惑的是,我可以做到以下几点:
void bar(const X& a) { /* */ }
bar(X{});
它没有抱怨。但是 bar()
不应该像 foo()
构造它的 return 类型一样构造它的参数 a
吗?
你不能,因为你说过你不希望编译器在你显式声明它时隐式使用它。
explicit X(X const& x)
但是 x
必须复制到 return 值中。只需将其更改为
X(X const& x)
一切正常。
当您 return 来自 foo
:
X foo()
{
X a{};
return a;
}
您正在将 a
隐式复制到 foo
的 return 中。但是复制构造函数被标记为 explicit
,所以这是不允许的。
我不确定是否有理由标记 copy/move 构造函数 explicit
。
我想你误解了explicit
的意思。 explicit
构造函数将不会用于隐式类型 CONVERSIONS/CASTS。这意味着
X foo(void){
X a{};
return a; // ERROR: no matching constructor found!
}
不会编译,因为您已经告诉编译器不要隐式使用复制构造函数。
我估计你要实现的是"move"而不是复制a
。只要 class 中有一个(正常的)移动构造函数,a
就会被移动而不是被复制——这是默认行为。实际上,即使使用 c++99,大多数编译器也足够聪明,可以优化这个副本。