簡體   English   中英

操作員超載內存泄漏

[英]operator overloading memory leak

最近我有一個用C ++要做的任務,用重載,交集等實現Set類作為重載運算符。 我在重載operator +()時遇到了問題。 我決定使用向量,並從某些算法的庫函數中受益。 問題是我不得不向構造函數傳遞數組指針和數組大小。 這使這個任務有點復雜...我可以編譯它,但是在執行“ z = a + b”操作時遇到了某種內存泄漏。 誰能解釋我在做什么錯?

class Set {
    int number; // array size (can't be changed)
    int *elems; // array pointer (same)

  public:

    Set();
    Set(int, int*); // (can't be changed)
    ~Set();

  friend Set operator+(const Set& X,const Set& Y){
    std::vector<int> v(X.number+Y.number);
    std::vector<int>::iterator it;

    it=std::set_union (X.elems, X.elems+X.number, Y.elems, Y.elems+Y.number, v.begin());
    v.resize(it-v.begin());

    Set Z;
    Z.number=v.size();
    Z.elems=&v[0];  

    return Z;
  }
};

Set::Set(){};
Set::Set(int n, int* array){
    number=n; 
    elems = array = new int[number];

    for(int i=0; i<number; i++) // creating Set
        std::cin >> elems[i];
    std::sort(elems, elems + number);
}

Set::~Set(){
    delete[] elems;
}

int main(){

   int* pointer;
   Set z;
   Set a = Set(5, pointer);
   Set b = Set(2, pointer);
   z=a+b;
}

我添加了拷貝構造函數和拷貝聲明,按照NathanOliver的建議更改了operator +(),現在我將傳遞給構造函數靜態數組。 仍然有內存泄漏,奇怪的是,即使在主目錄中只有類變量初始化時,我還是得到了該內存泄漏,是否與參數無關...有什么建議嗎? 我認為講師是有效的。

Set::Set(int n, int* array){
   number = n; 
   elems = array;
   std::sort(elems, elems + number);
}

Set::Set(const Set& s){
   number=s.number;
   elems=s.elems;
}
Set& operator=(const Set& X){

   if(this==&X)
     return *this;
   delete [] elems;
   elems=X.elems;
   number=X.number;
   return *this;

我使用gcc(tdm64-2)4.8.1編譯器。

  friend Set operator+(const Set& X,const Set& Y){
    std::vector<int> v(X.number+Y.number);
    std::vector<int>::iterator it;

    it=std::set_union (X.elems, X.elems+X.number, Y.elems, Y.elems+Y.number, v.begin());
    v.resize(it-v.begin());

    Set Z;
    Z.number=v.size();
    Z.elems=&v[0];  

    return Z;
  }

創建一個矢量,對其進行修改,然后將elems設置為指向該矢量包含的內容。 這樣做的問題是,當向量在函數末尾被破壞時,該向量所保留的內存將被釋放。 因此,您現在有了一個指向不再擁有的內存的指針。 嘗試執行任何操作都是未定義的行為。 您可以做的是創建一個新數組,將vector的元素復制到該數組中,然后將新數組分配給`elems

Set Z;
Z.number= v.size();
Z.elems= new int[z.number];
for (int i = 0; i < Z.number; i++)
    Z.elems[i] = v[i];

return Z;

其次,您需要為類定義一個復制構造函數和賦值運算符。 為此,請參閱: 什么是“三法則”?

最好的解決方案(但是我不能告訴您是否被允許這樣做)是在Set內部使用vector ,並使用兩次迭代器構造函數根據傳入的指針和length對其進行分配。

現在,如果不可能,則需要適當地管理類的內存:

  • 您需要一個復制構造函數和一個復制賦值運算符。
  • 在您的operator+您無法創建本地向量,然后獲取其內存地址,該內存將在操作員返回后立即消失。
  • 可能還有其他我沒聽懂的東西。

z=a+b ,將使用Set類的賦值運算符 您沒有定義此運算符的自定義版本,因此使用了默認的編譯器生成的版本 這個由編譯器生成的賦值operator=()只是簡單地執行成員復制

由於Set類中擁有原始擁有的指針 ,因此無法正常工作:默認的編譯器生成的operator=() 淺表復制指針,而應深度復制數據。

解決此問題的一種方法是定義您自己的operator=()版本,並注意對源數據進行適當的深度復制

請注意,在這種情況下,您還應該定義一個復制構造函數

但是更好的選擇是擺脫擁有的原始指針數據成員,而使用RAII構建塊類,例如std::vector

因此,例如,代替這些數據成員:

 int number; // array size (can't be changed) int *elems; // array pointer (same) 

您可能只有一個:

std::vector<int> elems;

如果這樣做,默認的編譯器生成的operator=()會很好地工作,因為它將復制std::vector數據成員(而不是原始擁有的指針),並且std::vector知道如何正確復制其內容不會泄漏資源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM