Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 减少复制构造函数调用_C++_Copy Constructor_Rvo - Fatal编程技术网

C++ 减少复制构造函数调用

C++ 减少复制构造函数调用,c++,copy-constructor,rvo,C++,Copy Constructor,Rvo,下面的代码是我正在处理的一个项目中的一个最小示例。主要的问题是我想减少对复制构造函数的调用次数,但我不清楚正确的方法 #include<iostream> class MyClass { public: MyClass() {std::cout << "Default Constructor\n";} MyClass(const MyClass &input) {std::cout << "Copy Constructor\n";}

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

#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;
}
  • 在a、b和c的构造中调用三个默认构造函数

  • 对于运算符+中的第一个参数和运算符+的返回,将调用两个复制构造函数

  • 赋值将a+b赋值给c的结果赋值

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

我考虑过一些解决方案,但没有一个能让我高兴:


  • 正如我所理解的,从阅读中,操作符+不应该有第一个参数的引用,因为这有助于链接临时参数。因此,这种复制构造函数似乎是不可避免的

  • 以下代码明显更快(因为没有复制构造函数调用):
    c=a;c+=b我可以使用这种格式编写代码,但这需要更精细的方法。我希望编译器比我自己做这些调整更聪明

  • 我可以实现一个函数
    add(MyClass&,constmyclass&,constmyclass&)
    但是这就失去了使用加法操作符的方便性(并且由于我使用的不同数据类型的数量,需要大量(无意识的)编码)

  • 我已经看了这些问题,但我没有看到任何可能提高本例性能的建议:

,及

对评论的答复:

  • 私有数据包括MPFR和MPFI,构造函数包括该数据的初始化。也许构造函数的不同实现是合适的,但我不确定

  • 我考虑过一个移动构造函数,但有时我也需要一个拷贝赋值。从这一点来看,它们似乎无法共存(或者至少在我第一次尝试时出现了一个错误)。看来这应该是最好的选择


您通过的是
lhs
副本。这就是为什么要调用额外的复制构造函数。修改您的
运算符+


MyClass操作符+(const MyClass&lhs,const MyClass&rhs)

在其他方面,为了最大限度地减少复制构造函数调用,我建议您定义move构造函数,并完美地转发操作符参数。移动构造函数:

MyClass(MyClass &&input) {std::cout << "Move Constructor\n";}
如果添加函数返回值并立即存储,例如:

MyClass c=something()+something();
这样就不会涉及复制构造函数


我举了一系列例子,其中我使用了
constmyclass&
参数和
operator+
以及
operator-
的完美转发参数。您可以看到,在最后一个示例中,这会产生不同,但在所有其他示例中,情况并非如此。这就是为什么我说“打对电话”。如果您必须操作可以像那样转发的对象,那么可能值得一试。

为什么不传递(常量)对
操作符+
函数的引用?“正如我所理解的,从阅读中,操作符+不应该有第一个参数的引用”-你在哪里读到的?根据协议,应该相互使用来实现。比如使用
operator+=
来实现
operator+
。在这种情况下,您应该通过值传递第一个参数。有足够的信息只建议您定义一个移动构造函数,您实际上不会有复制构造函数调用。我同意这种评估。此操作可以使用移动ctor和移动分配。坦白地说,如果您的设计允许的话,我会实现这两种方法(很可能是这样)。如果我这样做,那么我需要在operator+中创建一个新的MyClass对象来存储总和,因为我不想更改lhs和rhs。这不会减少构造函数调用的数量。
template<typename T>
    friend MyClass operator+(T &&lhs,T &&rhs) {return std::forward<T>(lhs);}
MyClass something() {return MyClass();}
MyClass c=something()+something();