2012-08-26 186 views
2

我想交換內部的一個對象。它的工作原理,但當我添加一個析構函數時,它給了我一個雙重的免費錯誤。有沒有辦法來防止這種情況?我說的方法是void swap(SimpleArray &object)交換一個對象本身內部

(很抱歉,如果你讀這之前,我曾在我的崗位錯誤信息...)

#include "TestType.h" 
class SimpleArray { 

    private: 
     TestType* pArray; 
     //TestType* temp; 
    public: 
     SimpleArray(TestType *array) 
     { 
      this->pArray = array; 
     } 
     ~SimpleArray() { delete[] pArray; } 
     SimpleArray() { pArray = 0;} 
     SimpleArray(const SimpleArray& arg){ pArray = arg.pArray; } 
     ~SimpleArray() { delete[] pArray; } 
     TestType * get() const{ return pArray; } 
     bool isNonNull() const { return pArray != 0; } 
     //TestType* pArray; 
     void reset(TestType*& p) {this->pArray = p; } 
     void reset() { pArray = 0; } 

     void swap(SimpleArray &object) { SimpleArray temp; temp = object; object = *this; *this = temp;} 
     TestType * release() { pArray = 0; return pArray; } 
     TestType& getReference(int a) { return *pArray; } 


}; 

這工作,但一旦我添加了析構它給了我一個「雙免費或損壞錯誤」。我該如何解決這個問題?這裏主要介紹它的功能。

bool testGetReleaseSwap() { 
    SimpleArray array1; 
    if (array1.get() != 0) 
     return false; 

    TestType* directArray1 = new TestType[100]; 
    array1.reset(directArray1); 
    if (array1.get() != directArray1) 
     return false; 

    TestType* directArray2 = new TestType[50]; 
    SimpleArray array2(directArray2); 

    array1.swap(array2); 
    if (array1.get() != directArray2 || array2.get() != directArray1) 
     return false; 

    array2.swap(array1); 
    if (array1.get() != directArray1 || array2.get() != directArray2) 
     return false; 

    array1.swap(array1); 
    if (array1.get() != directArray1) 
     return false; 

    if (array1.release() != directArray1 || array2.release() != directArray2) 
     return false; 

    if (array1.get() != 0 || array2.get() != 0) 
     return false; 

    delete[] directArray1; 
    delete[] directArray2; 

    return true; 
} 
+2

的可能重複【什麼是三個規則?(http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three)你丟失的拷貝賦值運算符,而你的拷貝構造函數做一個淺拷貝,讓兩個對象擁有相同的數組。 –

+0

感謝幫助。修復了這個問題。 – avoliva

回答

6

在這裏瑣碎的方式是在結束時調用temp.release()如果您swap方法來防止雙重缺失。

儘管如此,潛在的問題要深得多。在C++中,始終保持誰擁有某些內容的嚴格語義至關重要,例如需要刪除的內存區域。

一個頻繁的模式是,分配東西的對象也負責清理而不是其他人。這很符合SimpleArray,但複製構造函數會將其分開,因爲它會使業主數量增加!

要實現你必須投資更多的工作(引用計數等)共享數據的語義,或者你有禁止複製陣列,使拷貝構造函數私有。

乾淨方式來修復swap而不復制對象。將工作:

void swap(SimpleArray &object) { 
    TestType* temp = object.pArray; 
    object.pArray = this->pArray; 
    this->pArray = temp; 
} 

std::swap(object.pArray, pArray);作品以及)

由於交換的存儲器區域的陣列適合很好對於單一所有者模式,這裏出了什麼問題只是使用完整的對象副本。

您應該閱讀C++中的資源管理和所有權語義。除非您完全知道誰擁有,否則您的代碼始終容易出錯。

+0

仍然收到相同的錯誤。 – avoliva

+0

抱歉,他們工作,但仍有一堆內存仍然存在。部分任務也是確保沒有內存泄漏。 – avoliva

+0

謝謝。在看了三條規則之後,我在我的課堂上做了一個operator = method。在交換沒有按預期工作之前,但現在它完美地工作。 – avoliva

2

在我看來,你正試圖實現具有淺拷貝語義(並且可能寫入時複製)的類。要做到這一點,您需要跟蹤共享數據的其他所有者還有多少,並且需要銷燬擁有的對象時,該數量達到零。您可以使用std::shared_ptr或自己實現引用計數。

至於那個具體例子中的真實問題,看看你拷貝的構造函數正在做什麼。它不是複製,而是簡單地將另一個引用(指向特定的指針)引用到已由其參數擁有的對象。這本身已經足以獲得雙倍免費,而你的測試用例只是暴露了這個問題。

+0

那麼如何修復複製構造函數? – avoliva

+0

@ user1447974如果您沒有實際實現淺拷貝或寫時拷貝的意圖,**拷貝ctor **需要實際**拷貝**它的參數數組。 – pmr

+0

所以我想做一個淺拷貝?我想我現在正在做的事情實際上是一個深層複製? – avoliva