首页 > 解决方案 > C++:两个自定义对象的总和,避免复制构造函数的双重调用

问题描述

在下面的示例中,我有两个类,第一个动态分配一个整数,第二个是第一个类的容器。

当我对两个容器对象 ( operator+()) 求和时,复制构造函数被调用了两次。在我看来,第二个发生在operator+()函数的“return”语句期间。 如何优化以避免复制构造函数的第二次调用?

显然,这对于我不想做两个深拷贝的更复杂的应用程序具有代表性,如果逻辑上认为总和只需要创建一个对象(然后返回):

(看起来可能有很多代码,但只有运算符和构造函数才能有效地进行求和。我避免使用析构函数以使其更加混乱)。

主要课程

int main()
{
  NumberContainer a{1};
  NumberContainer b{2};
  NumberContainer c = a + b; // Copy constructor called twice!
  return 0;
}

号码类:

class Number
{
public:
  int* num;

  Number(int num) : num{new int{num}}
  {}
// Destructor...
};

容器类:

class NumberContainer
{
private:
  Number _numObj;
public:
  NumberContainer(int num) : _numObj{Number{num}}
  {}

  NumberContainer(const NumberContainer& source) : NumberContainer{*(source._numObj.num)}
  {
    std::cout<<"Copy constructor called" << std::endl;
  }

  NumberContainer(NumberContainer&& source) : NumberContainer(*(source._numObj.num))
  {
    std::cout<<"Move constructor called" << std::endl;
  }

  NumberContainer& operator=(const NumberContainer& source)
  {
    *(_numObj.num) = *(source._numObj.num);
    std::cout<<"Copy assignment called" << std::endl;
    return *this;
  }

  NumberContainer& operator=(NumberContainer&& source)
  {
    _numObj.num = source._numObj.num;
    source._numObj.num = nullptr;
    std::cout<<"Move assignment called" << std::endl;
    return *this;
  }

  NumberContainer& operator+=(const NumberContainer& source)
  {
    *(_numObj.num) += *(source._numObj.num);
    return *this;
  }

  NumberContainer operator+(const NumberContainer& source) const
  {
    NumberContainer copy{*this};
    return copy+=source;
  }
// Destructor...
};

标签: c++classconstructoroperator-overloadingcopy-constructor

解决方案


在运算符 + 中创建中间对象没有什么意义。

  NumberContainer operator+(const NumberContainer& source) const
  {
    NumberContainer copy{*this};
    return copy+=source;
  }

像这样定义

  NumberContainer operator+(const NumberContainer& source) const
  {
    return     *(_numObj.num) + *(source._numObj.num);
  }

复制构造函数也可以定义为

  NumberContainer(const NumberContainer& source) : _numObj{*(source._numObj.num)}
  {
    std::cout<<"Copy constructor called" << std::endl;
  }

推荐阅读