使用重载 + 和 += 运算符销毁的临时变量

Temporary variable destroyed with overloaded + and += operator

本文关键字:变量 运算符 重载      更新时间:2023-10-16

>我得到一个段错误,因为我相信我的临时变量在运算符使用完之前就被销毁了(释放分配的内存)。这是我的主要代码:

int main(int argc, char *argv[])
{
  Bcd b1 = Bcd(100), b2 = Bcd(20), b3 = Bcd(50);
  b3 += b1 + b2;
  return 0;
}

我在析构函数中放了一个 print 语句,输出如下:

sum
destroying 120
sum
segmentation fault

我不明白为什么会发生这种情况。临时变量 b1+b2 似乎在第二次按总和使用之前就被销毁了。临时变量 b1+b2 不应该在 main 的那行末尾之前有效吗?我是否正确地实现了运算符重载函数,或者我的代码是否存在我没有考虑的其他问题?

我的自定义类定义如下:

class Bcd
{
 public:
  Bcd();
  Bcd(const char* num);
  Bcd(const Bcd &num);
  Bcd(const int num);
  ~Bcd();
  int getLength() const;
  Bcd& operator=(const Bcd &rhs);
  Bcd& operator+=(const Bcd &rhs);
  const Bcd& operator +(const Bcd &rhs) const;
  std::string toString() const;
private:
  //takes a character and places is at number[index]. If that index does 
  //not exist, allocates memory for that number and then sets number[index].
  void modifyNumber(char num, int index);
  char* number;
  int length;
  int size;
};

.c文件的重要部分在这里:

Bcd& Bcd::operator +=(const Bcd &rhs){
  int minSize, i;
  char result[2] = {0};
  printf("sumn");
  if(this->getLength() < rhs.getLength())
    minSize = this->getLength();
  else
    minSize = rhs.getLength();
  for(i = 0; i < minSize; i++) //SEGFAULT from accessing rhs.number[0]
      this->modifyNumber(this->number[i] + rhs.number[i], i);
  if(this->getLength() < rhs.getLength()){
      for(;i < rhs.getLength(); i++)
          this->modifyNumber(rhs.number[i], i); 
    }
  else{
      for(;i < this->getLength(); i++)
          this->modifyNumber(this->number[i], i);
    }
  return *this;
}
const Bcd& Bcd::operator +(const Bcd &rhs) const
{
  return Bcd(*this) += rhs;
}
Bcd::Bcd(const Bcd &num)
{
  length = num.length;
  size = num.size;
  //allocate memory for number
  number = new char[length];
  for(int i = 0; i < length; i++)
      number[i] = num.number[i];
}

这正是它应该发生的方式。可能更正确的说法是,被销毁的不是临时b1 + b2,而是二进制+实现中的临时Bcd(*this) += rhs

+的实施

const Bcd& Bcd::operator +(const Bcd &rhs) const
{
  return Bcd(*this) += rhs;
}

尝试返回绑定到临时的引用。临时在函数退出之前被销毁,引用保持挂起状态。调用方收到"死"引用。行为未定义。

这不是通过附加到临时的引用来延长临时生存期的上下文之一。

不能从二进制+返回引用。您根本没有要返回引用的内容。相反,按值返回

Bcd Bcd::operator +(const Bcd &rhs) const
{
  return Bcd(*this) += rhs;
}

此实现确实会返回一个临时的,该临时将用作b1 + b2。而且这个临时不会过早地被摧毁。

一个问题是 operator+ 应该返回对象的副本,而不是引用。我认为您的代码创建了一个临时并返回其引用,这是一个很大的 NO。

编译器应该警告过您。如果使用GCC,则每次都使用-W -Wall。这将有很大帮助。

现在这很奇怪。我用我的 GCC 对此进行了测试,如果我在 -O2 或 -O3 优化的情况下进行编译,我只会收到警告。

相关文章: