2014-07-17 46 views
-1

我有關於下面的代碼,它崩潰的問題。我在testfunction()中創建一個局部變量,然後將它(變量「y」)推入列表中。這個變量有一個對象類型爲Ball的成員指針「b」。據我所知,這個局部變量「y」在堆棧中,所以它的析構函數將在testfunction()完​​成後調用。另外,據我所知,一個向量將一個對象「複製」到它的列表中。從我所瞭解到的情況來看,如果在其類中存在一個指針,那麼最好刪除析構函數中的指針。所以,在例子的析構函數中有「delete b」。崩潰問題 - 使用指針和析構函數的C++代碼設計

我遇到的問題是對象y.b在testfunction()完​​成時被銷燬。在main()中,我能夠看到「name」的值和「b」的地址,但對象「b」已經被刪除。我想避免這一點。

我認爲有代碼設計/使用指針與引用等問題請引導我在正確的方向,我是一個白癡!

#include <iostream> 
#include <string> 
#include <vector> 
using namespace std; 

class Ball 
{ 
    public: 
     int a; 

     Ball() 
     { 
      a = 0; 
     } 

     ~Ball() 
     { 
      cout << "destroyed Ball()" << endl; 
     } 
}; 

class Example 
{ 
    public: 
     string name; 
     Ball* b; 

     Example() 
     { 
      name = ""; 
      b = NULL; 
     } 

     ~Example() 
     { 
      cout << "destroying Example()" << endl; 
      delete b; 
     } 
}; 

void testfunction(vector<Example>& list) 
{ 
    cout << "entered testfunction1()" << endl; 

    Example y; 
    y.name = "myName"; 
    y.b = new Ball(); 
    y.b->a = 5; 

    cout << "y.b->a = " << y.b->a << endl; 
    list.push_back(y); 

    cout << "exit testfunction1()" << endl; 
} 

void testfunction2() 
{ 
    cout << "entered testfunction2()" << endl; 
    Example* y = new Example(); 
    cout << "exit testfunction2()" << endl; 
} 

int main() { 
    vector<Example> list; 
    testfunction(list); 
    //testfunction2(); 

    if(list[0].b == NULL) 
     cout << "b is null" << endl; 
    else 
     cout << "b is not null" << endl; 

    cout << list[0].name << endl; 
    cout << list[0].b << endl; 
    cout << "list[0].b->a = " << list[0].b->a << endl; 
    return 0; 
} 
+0

仍指出這將是更適合只是爲了擺脫在這個例子中每一個指針。 – chris

+0

嗨@chris,謝謝你的建議。我也想過這個。如果擺脫球*並把它變成球。檢查會員Ball b是否存在的最佳方法是什麼? – codeshark

+0

使用'boost :: optional'作爲可選對象。 – chris

回答

1

爲您的課Example定義複製構造函數和代理操作符。 這些應當在向量上推回時正確地複製您的對象(創建一個複製的Ball對象)。

Example(const Example& a) 
{ 
    name = a.name; // attention no dynamic allocation 
    cout << "copy" <<endl; 
    if (a.b) { 
     b = new Ball(*a.b); // create a new duplicated Ball 
    } 
    else b = NULL; 
} 

你的例子中的問題是當你回推對象時調用默認的拷貝構造函數。它複製成員,因此指向球的指針被複制,而不是指向的對象。

另一種替代方案可能是您的Ball*shared_ptr<Ball>替換(因此,new Ballmake_shared<Ball>()和對象的delete bb.reset())。其原理是這個智能指針跟蹤對象所指向的時間的使用次數,以便它不會刪除它兩次,但只有當它不再在任何地方使用時。

2

由於class Example有一個指針成員,它試圖擁有一個動態分配的資源,它需要非默認的複製操作,換句話說,它需要用戶定義的複製構造函數和賦值操作符。

裏面testfunction,當您複製yvector,本地yy copied to the vector指向同樣的Ball對象。功能結束時銷燬本地y,並刪除Ball。但是,刪除Bally in vector

void testfunction(vector<Example>& list) 
{ 
    // ... 

    Example y; 
    y.name = "myName"; 
    y.b = new Ball(); 
    y.b->a = 5; 

    list.push_back(y); 

    // ... 
} // <-- destructor for Example y is called and y.b is deleted 
+0

'Example'不需要非默認的拷貝構造函數,因爲它有一個指針成員。它可能需要它們,因爲它試圖擁有一個動態分配的資源。另一個解決方案是不擁有它。 – juanchopanza

+0

我認爲'有一個指針成員'意味着'擁有一個動態分配的資源',但也許以一種隱含的方式。無論如何,我會改進這部分,並明確表示,謝謝! – Alper