减少复制构造函数调用

Reduce Copy Constructor Calls

以下代码是我正在处理的项目中的一个最小示例。主要问题是我想减少对复制构造函数的调用次数,但我不清楚这样做的正确方法。

#include<iostream>

class MyClass
{
public:
    MyClass() {std::cout << "Default Constructor\n";}
    MyClass(const MyClass &input) {std::cout << "Copy Constructor\n";}
    MyClass & operator=(const MyClass &input) 
         {std::cout << "Assignment\n"; return *this;}
    MyClass & operator+=(const MyClass &input) {return *this;}
    friend MyClass operator+(MyClass lhs,const MyClass &);
};

MyClass operator+(MyClass lhs,const MyClass &rhs) 
    {lhs+=rhs;return lhs;}

int main()
{
    MyClass a,b,c;
    c=a+b;
    return 0;
}

当我运行代码时,输​​出是:

Default Constructor
Default Constructor
Default Constructor
Copy Constructor
Copy Constructor
Assignment

主要问题:在我的应用程序中,复制构造函数是昂贵的(它涉及内存分配)。另一方面,分配相对便宜。减少对复制构造函数的调用的正确方法是什么?

我考虑了一些解决方案,但是none让我很开心:

Copy constructor called twice, Copy constructor called twice, and Conditions for copy elision

对评论的回复:

您正在通过副本 lhs。这就是为什么你有额外的复制构造函数调用。修改你的 operator+:

MyClass operator+(const MyClass &lhs, const MyClass &rhs)

为了尽量减少复制构造函数调用,我建议您定义移动构造函数并完美转发运算符参数。移动构造函数:

MyClass(MyClass &&input) {std::cout << "Move Constructor\n";}

完美转发运算符:

template<typename T>
    friend MyClass operator+(T &&lhs,T &&rhs) {return std::forward<T>(lhs);}

通过正确的调用,您的运算符将涉及移动构造函数而不是复制构造函数。例如,如果您添加来自函数的对象并立即存储结果(例如 MyClass c=a+b; 而不是 MyClass c;c=a+b;),感谢 RVO 您可以保存复制构造函数。

假设您有一个 return 是 MyClass 实例的函数:

MyClass something() {return MyClass();}

如果添加函数 return 值并立即存储它们,例如:

MyClass c=something()+something();

那么将不会涉及复制构造函数。

我提供了一系列示例 here,其中我将 const MyClass& 参数与 operator+ 一起使用,将完美转发参数与 operator- 一起使用。您可以看到它在最后一个示例中有所不同,但在所有其他示例中都没有。这就是为什么我说 "with the right calls"。如果你必须像那样操作可以转发的对象,那可能值得一试。