为何默认拷贝构造函数添加explicit会导致无法返回对象?
问题原因解析:explicit构造函数导致返回值编译失败
问题场景
以下是最小可复现示例:
class A { public: A() = default; explicit A(const A&) = default; // explicit A(A&) = default; ///添加这个没有作用 explicit A(A&&) = default; A& operator=(const A&) = default; A& operator=(A&&) = default; }; auto dummy_a() { A a; return a; //报错:no matching function for call to 'A::A(A)' } int main() { const auto a = dummy_a(); }
编译上述代码会出现如下错误,除非移除拷贝构造函数或移动构造函数的explicit关键字:
main.cpp: In function 'auto dummy_a()': main.cpp:14:12: error: no matching function for call to 'A::A(A)' 14 | return a; //no matching function for call to 'A::A(A)' | ^ main.cpp:4:5: note: candidate: 'constexpr A::A()' 4 | A() = default; | ^ main.cpp:4:5: note: candidate expects 0 arguments, 1 provided
原因分析
- 执行
return a;时,编译器需要将局部变量a转换为函数返回值类型(即A),这个过程依赖拷贝构造函数或移动构造函数来创建返回对象。 explicit关键字的作用是限制构造函数只能用于显式类型转换,禁止编译器隐式调用它。你给拷贝构造函数(explicit A(const A&))和移动构造函数(explicit A(A&&))都加了这个限制,导致编译器无法在返回值的场景中隐式调用它们。- 即使编译器可能会做返回值优化(RVO)来避免实际的拷贝/移动操作,C++标准仍然要求对应的构造函数必须是可隐式调用的,否则编译无法通过。
- 错误提示中提到的
A::A(A)是编译器尝试寻找的非const左值引用拷贝构造函数,但你并未定义它;而你定义的const左值和右值版本都是explicit的,无法被隐式调用,最终编译器找不到可用的构造函数,因此报错。
内容的提问来源于stack exchange,提问作者Antonio
相关产品推荐
相关产品推荐

