1

我正在阅读 Stroustrup C++ 11 书,遇到了双重免费异常。我知道它会释放内存两次,但我不明白为什么它会发生在通过副本传递的函数中:

#include <iostream>

using namespace std;

namespace ALL_Vector { 

  class Vector {
    public:
      // Intitialize elem and sz before the actual function
      Vector(int size) :elem {new double[size]}, sz {size} {};
      ~Vector() {delete[] elem;};

      double& operator[](int i) {
        return elem[i];
      };
      int size() {return sz;};
    private:
      double* elem;
      int sz;
  };


  void print_product(Vector& y) {
    double result {1};

    for (auto x = 0; x < y.size() ; x++){
      if (y[x] > 0) {result *= y[x]; };
    }

    cout << "The product of Vector y is: " << result << ", or so it would appear ;)\n";
  } 

}


/*
  Self test of the Vector class.  
*/

int main(){  
    ALL_Vector::Vector myVector(15);
    cout << "The size of Vector y is: " << myVector.size() << "\n"; 
    myVector[0] = 12;
    myVector[2] = 7;
    myVector[3] = 19;
    myVector[4] = 2;

    ALL_Vector::print_product(myVector);

  return 0;
}

print_product() 正在使用 Vector 类并创建一个具有重复内容的新 Vector?为什么这会导致双重免费?我假设在这种情况下 RIIA 以某种方式与 Vector::~Vector() 交互,类似于竞态条件?

我知道如果我改变它以通过引用传递它的参数,它将避免双重释放。我试图更好地理解通过副本传递的问题。

谢谢!

4

2 回答 2

5

实际上,您正在调用 print_product 并引用myVector,所以一切都很好。
麻烦从myVector按值传递开始,因为默认的复制构造函数将复制elem指针而不是复制整个数组。
两个ALL_Vector::Vector elem指针都将引用相同的内存存储,因此被删除两次。
要解决这个问题,您必须实现复制构造函数来创建一个新数组并复制所有元素。

于 2016-01-22T10:12:15.840 回答
1

如果Vector按值传递,则调用复制构造函数,而不是您已实现的构造函数。在这种情况下,elem不会复制指针,而是将指针复制到新对象中,然后被析构函数删除两次。您必须实现一个复制构造函数,该构造函数分配一个新elem元素并复制所有元素。

于 2016-01-22T10:20:35.007 回答