C++ 在C+;中按值返回构造的对象时避免复制构造函数调用+;11
我有一个没有复制构造函数的类,我仍然希望通过值返回它。以下MCVE在C++17中编译:C++ 在C+;中按值返回构造的对象时避免复制构造函数调用+;11,c++,c++11,C++,C++11,我有一个没有复制构造函数的类,我仍然希望通过值返回它。以下MCVE在C++17中编译: class Cls { public: Cls(int x) {} Cls(const Cls& c) = delete; }; Cls f(int x) { return Cls(x); } int main() { f(0); } 但不是在C++11中: $ g++ prog.cc -Wall -Wextra -std=c++11 prog.cc: I
class Cls {
public:
Cls(int x) {}
Cls(const Cls& c) = delete;
};
Cls f(int x) {
return Cls(x);
}
int main() {
f(0);
}
但不是在C++11中:
$ g++ prog.cc -Wall -Wextra -std=c++11
prog.cc: In function 'Cls f(int)':
prog.cc:9:17: error: use of deleted function 'Cls::Cls(const Cls&)'
9 | return Cls(x);
| ^
prog.cc:5:5: note: declared here
5 | Cls(const Cls& c) = delete;
| ^~~
据我所知,原因是编译器不允许优化复制,即使在这种情况下它应该是微不足道的
我希望返回std::move(Cls(x))
可以工作并避免复制构造函数,但它会给出相同的错误
我是否可以在不定义复制构造函数(或assignment运算符)的情况下修复此问题
我已经查看了相关问题,但没有找到重复的问题。改为实现移动构造函数 在C++17中,编译器必须复制或移动对象,而不必复制或移动对象。但对于C++11,您没有此功能,但您可以为您的案例采取行动:
Cls(Cls&& c) = default;
据我所知,原因是编译器不允许优化复制,即使在这种情况下它应该是微不足道的
没错
我希望返回std::move(Cls(x));将工作并避免复制构造函数,但它会给出相同的错误
这不是解决办法<代码>标准::移动(Cls(x))不会做任何事情,因为Cls(x)
已经生成一个pr值。在极少数情况下,如返回函数参数时,应将返回值转换为右值。此外,如果可以从该右值移动并构造另一个实例,则只能使用Cls
右值而不进行复制,而在原始代码段中则不是这样
我是否可以在不定义复制构造函数(或assignment运算符)的情况下修复此问题
您可以按照的建议定义移动构造函数。这允许返回类型为Cls
的临时对象,但仍不允许复制。您将其称为仅移动类型,而仅移动的主要标准类型之一是std::unique_ptr
最后一点,我认为这是一个很好的实践,建议处理移动构造/分配,不要依赖于隐式删除这些特殊的成员函数
我是否可以在不定义复制构造函数(或assignment运算符)的情况下修复此问题
在您的案例中有两个选项:
Cls(Cls&& c) = default;
- 定义移动构造函数:
Cls(Cls&& c) = default;
Cls f(int x) { return {x}; }
- Use,它允许不调用复制/移动构造函数,它需要一个非显式构造函数:
Cls(Cls&& c) = default;
Cls f(int x) { return {x}; }
在C++17中,您有“保证”复制省略(或“非物质化值传递”),因此
返回Cls(x)代码>就可以了。即使编译器可以省略副本(因此不会调用实际的副本构造函数),也需要一个副本构造函数。您明确禁止复制您的类型。“在C++17中,编译器可以做”-编译器实际上需要这样做。@Fureeish确实是。