复制构造函数和重载的加法运算符

Posted

技术标签:

【中文标题】复制构造函数和重载的加法运算符【英文标题】:Copy constructor and overloaded addition operator 【发布时间】:2018-11-20 01:22:45 【问题描述】:

我正在审查 C++ 中的运算符重载。只是为了好玩,我正在实现一个 BigInt 类。

我要为其重载的第一个运算符是加法运算符。我决定将此运算符重载为友元非成员函数。这是这段代码的 MWE:

#include <cassert>
#include <iostream>
#include <string>

class BigInt
 public:
  friend BigInt operator+(const BigInt &bi1, const BigInt &bi2);

  BigInt() 
  explicit BigInt(const std::string &in) 
    if (in.size() != 0) 
      for (auto cc = in.rbegin(); cc != in.rend(); ++cc) 
        value_.push_back(*cc);
      
    
  
  std::string value() 
    std::string actual_value;  // Reversed string.
    for (auto cc = value_.rbegin(); cc != value_.rend(); ++cc) 
      actual_value.push_back(*cc);
    
    return actual_value;
  

 private:
  std::string value_;  // String of digits as characters.
;

BigInt operator+(const BigInt &bi1, const BigInt &bi2) 
  BigInt result;

  result.value_ = "4421";
  return result;


int main() 
  std::cout << "Test addition operator... ";
  std::string number"1234";  // Number 1,234.
  BigInt mm(number);
  std::string number_ten"10";  // Number 10.
  BigInt nn(number_ten);

  BigInt mm_nn = mm + nn;

  std::string expected_result"1244";  // 1,234 + 10 = 1,244.
  assert(mm_nn.value() == expected_result);
  std::cout << "ok." << std::endl;

这段代码模拟了加法的行为。它编译并运行。然而,当我为 BigInt 类添加复制构造函数时,此代码停止工作。 IE。如果我将其添加到类声明中:

explicit BigInt(const BigInt &amp;in): value_(in.value_)

代码甚至无法编译。编码的加法函数返回BigInt 的构造实例的副本。为此,必须定义一个复制构造函数。如果我自己没有定义它,那么编译器会这样做。编译器会产生什么我没有通过添加的复制构造函数产生?这是我得到的编译错误:

$ g++ -std=c++14 -g mwe.cpp 
mwe.cpp: In function ‘BigInt operator+(const BigInt&, const BigInt&)’:
mwe.cpp:34:10: error: no matching function for call to ‘BigInt::BigInt(BigInt&)’
   return result;
          ^
mwe.cpp:9:3: note: candidate: BigInt::BigInt()
   BigInt() 
   ^
mwe.cpp:9:3: note:   candidate expects 0 arguments, 1 provided
mwe.cpp: In function ‘int main()’:
mwe.cpp:44:23: error: no matching function for call to ‘BigInt::BigInt(BigInt)’
   BigInt mm_nn = mm + nn;
                       ^
mwe.cpp:9:3: note: candidate: BigInt::BigInt()
   BigInt() 
   ^
mwe.cpp:9:3: note:   candidate expects 0 arguments, 1 provided

据此,编译器似乎需要一个我没有提供的复制构造函数。现在...如果我删除 explicit 关键字,一切正常。但是,我已经看到了具有显式复制构造函数的实现,例如:Explicit copy constructor

我错过了什么?为什么我不能在重载加法运算符时使这个复制构造函数显式?一般来说,拷贝构造函数应该显式吗?

【问题讨论】:

Unrelated ,你可以简单地让你的参数化 cntor 像这样:explicit BigInt(const std::string &amp;in) :value_(in.rbegin(), in.rend()) &lt;algorithm&gt; 中还有一个名为std::reverse 的函数。 换句话说,你可以把这个函数写成:std::string value() return std::string(value_.rbegin(), value_.rend()); 问题是你的复制结构是explicit,所以return result;不起作用,你需要return BigIntresult;。只需使您的复制构造函数不明确。 “为什么我不能明确地说明这个复制构造函数” - 你为什么想要明确地说明它?这样做的原因是有限的、具体的,但它们是例外的,而不是常规的,我在这里看不到支持这种例外情况的证据。你问,“编译器会产生什么我没有产生的东西”。实际上,您应该问“我在生成什么编译器不是?”,答案是用于调用复制构造的限制性更强的机制;明确取消所有隐式复制的资格。 这段代码用GCC 4.9.2正确编译。你用的是什么编译器? 【参考方案1】:

制作复制构造函数explicit 没有意义。删除它。

BigInt(const BigInt &in): value_(in.value_) 

explicit 复制构造函数的概念问题

创建一个复制构造函数explicit 使得从函数返回一个对象是不可能的。

让我们将您的代码简化为以下内容:

struct BigInt

   BigInt() 
   explicit BigInt(const BigInt &in) 
;

BigInt operator+(const BigInt &bi1, const BigInt &bi2)

   BigInt result;
   return result;


int main() 

return result 行中,编译器依赖复制构造函数返回一个对象。如果复制构造函数是显式的,则无法将 BigInt 构造为返回值。

尝试使用:

BigInt operator+(const BigInt &bi1, const BigInt &bi2)

   BigInt result;
   return BigInt(result);

是徒劳的,因为这相当于:

BigInt operator+(const BigInt &bi1, const BigInt &bi2)

   BigInt result;
   BigInt result1(result);
   return result1;

无论您在函数中做什么,问题仍然存在。

【讨论】:

我同意。但是,编译器无法找到BigInt::BigInt(BigInt&amp;) 的匹配项,这很奇怪。即使您从构造函数中删除const,也会出现此错误。 好的,我现在明白了。 explicit 禁止编译器隐式调用构造函数,即使没有类型转换。 @R Sahu 为什么我不能在重载加法运算符时显式显示这个复制构造函数?你还没有回答这个 OP 问题。 @JeJo,RVO 可能在那里玩。 IIRC,C++17 添加了一些条款,使得 RVO 在某些结构中是强制性的。 从C++17开始,如果你return一个prvalue然后prvalue初始化结果对象,没有临时对象。 (当函数调用初始化一个变量时,该变量就是结果对象)。返回纯右值的代码示例与返回左值的示例大不相同。

以上是关于复制构造函数和重载的加法运算符的主要内容,如果未能解决你的问题,请参考以下文章

关于拷贝构造函数和运算符重载的问题

c++中拷贝构造函数和赋值运算符重载本质上一样么

C ++中的复制构造函数和=运算符重载:通用函数可能吗?

复数类重载加法减法和乘法运算符

c++ 拷贝构造函数与赋值运算符重载函数的区别是

为啥我能够为 QObject 子类创建复制构造函数并重载赋值运算符?