2010-10-25 145 views
0

我有一個簡單的類叫object,我遇到了問題。 Theres一個方法,如果我叫它會導致段錯誤。我不明白爲什麼。C++類指針刪除segfaulting

typedef class object 
{ 
    private: 
     short id; 
     std::string name; 
     SDL_Rect offset; 

    public: 
     object(); 
     object(short i, std::string n); 
     ~object(); 
     object(const object &o); 
     object& operator = (const object &o); 
     std::string get_name(); 
     void set_name(std::string n); 
} object; 

object::object() 
{ 
    id = 0; 
    name = ""; 
    offset.x = 0; 
    offset.y = 0; 
    offset.w = 0; 
    offset.h = 0; 
} 

object::object(short i, std::string n) 
{ 
    id = i; 
    name = n; 
    offset.x = 0; 
    offset.y = 0; 
    offset.w = 0; 
    offset.h = 0; 
} 

object::~object() 
{ 
    delete &offset; 
    delete &id; 
    delete &name; 
} 

object& object::operator=(const object &o) 
{ 
    if(this != &o) 
    { 
     delete &name; 
     name.assign(o.name); 
     delete &id; 
     id = o.id; 
     delete &offset; 
     offset = o.offset; 
    } 
    return *this; 
} 

object::object(const object &o) 
{ 
    id = o.id; 
    name = o.name; 
    offset = o.offset; 
} 

// Functions 
std::string object::get_name() 
{ 
    return name; 
} 

void object::set_name(std::string n) 
{ 
    name = n; 
} 

而且我的main.cpp

int main(int argc, char** argv) 
{ 
    struct object *a = new object(0, "test"); 
    struct object *b = new object(1, "another test"); 

    printf(a->get_name().c_str()); 
    printf("\n"); 
    printf(b->get_name().c_str()); 
    b = a; 
    printf("\n"); 
    printf(b->get_name().c_str()); 
    a->set_name("Another test"); 
    printf("\n"); 
    printf(a->get_name().c_str()); 

    delete a; 
    printf("\nDeleted a"); 
    delete b; 
    printf("\nDeleted b"); 

    return 0; 
} 

如果我打電話a->set_name("Another test");,我得到一個段錯誤。如果我不打電話,沒有問題,一切正常。我可能錯過了一些簡單的東西,但我找不到它。它在賦值時不會出現段錯誤,但是如果該行在那裏,則在刪除指針時會崩潰。

+8

你有[一個很好的C++的書(http://stackoverflow.com/questions/388242/the-definitive-c++-book-guide-and-list) ?如果沒有,我強烈建議您購買一個。 – 2010-10-25 16:19:22

+0

是的..讓自己一本C++書.. :) – baash05 2010-10-26 00:36:58

回答

4

因爲你沒有任何new在構造函數中,這是錯誤的在析構函數delete什麼。只要將析構函數留空即可,甚至更好,完全擺脫它。編譯器生成的析構函數完全是你想要的(沒有)。您也不必手動編寫拷貝構造函數和拷貝賦值操作符,只需將它們扔掉即可。

也不需要動態創建對象,而使用本地C++輸入/輸出功能打印字符串要容易得多。你可以擺脫使用默認參數重載構造函數。通過引用到const來傳遞和返回字符串比通過值傳遞它們更有效。最後但並非最不重要的,讓我們是const正確的。這裏是我的代碼的清理:

#include <iostream> 

class object 
{ 
    short id; 
    std::string name; 
    SDL_Rect offset; 

public: 

    object(short i = 0, const std::string& n = ""); 
    const std::string& get_name() const; 
    void set_name(const std::string& n); 
}; 

object::object(short i, const std::string& n) : id(i), name(n) 
{ 
    offset.x = 0; 
    offset.y = 0; 
    offset.w = 0; 
    offset.h = 0; 
} 

const std::string& object::get_name() const 
{ 
    return name; 
} 

void object::set_name(const std::string& n) 
{ 
    name = n; 
} 

int main(int argc, char** argv) 
{ 
    object a(0, "test"); 
    object b(1, "another test"); 

    std::cout << a.get_name() << "\n"; 
    std::cout << b.get_name() << "\n"; 

    b = a; 
    std::cout << b.get_name() << "\n"; 

    a.set_name("Another test"); 
    std::cout << a.get_name() << "\n"; 
} 
+0

錯過了那一個。指針還不是很好。我刪除了析構函數,並重新編譯。但我仍然遇到段錯誤。 – Bocochoco 2010-10-25 16:21:41

+0

@Bocochoco:那是因爲你在int main()中設置了b = a。所以你刪除了同一個指針兩次。 – Puppy 2010-10-25 16:29:57

+1

啊,所以我的複製和複製分配功能不能正常工作。 – Bocochoco 2010-10-25 17:29:35

3
delete &name; 

您只能通過調用new獲得指標deletename是該類的成員變量;你不能刪除它,也不會必須。當類被銷燬時,它也會銷燬任何成員變量。

這只是如果有成員是指針(比如,如果你有std::string* name),您就必須確保正確地清除它們,但即使如此,你應該更喜歡使用智能指針像scoped_ptrshared_ptr,或unique_ptr (如果你的實現支持它)。

0

namestring並管理自己的記憶。你在結構中的聲明是正確的,你可以在任何已經存在的值的基礎上加上assign。當結構超出範圍時不需要做任何事情。

請注意,您的get_name方法返回一個新的副本,因爲它返回值。你可以改爲返回到什麼是在這樣的結構的引用,所提供的返回值所屬的結構後不使用超出範圍:

const string& get_name() { return name; } 

,則應該更換二傳手聲明如下,因爲沒有好處傳遞一份副本(值過多傳遞是新C++開發人員的常見錯誤)。

void set_name(const string& newValue)