1

noob here。我正在做一個練習,編譯器報告沒有錯誤,但是當我嘗試運行它時,程序崩潰。構造函數和運算符=具有動態內存分配

我試圖運行一個小程序,行使牛類的不同方法。它顯式地具有:構造函數,默認構造函數,複製構造函數,析構函數,重載賦值運算符以及顯示其內容的方法。

我把整個項目:

類規範:

//cow.h -- For project Exercise 12.1.cbp 

class Cow 
{ 
    char name[20]; // memory is allocated in the stack 
    char *hobby; 
    double weight; 
public: 
    Cow(); 
    Cow(const char *nm, const char *ho, double wt); 
    Cow(const Cow &c); 
    ~Cow(); 
    Cow & operator=(const Cow &c); 
    void ShowCow() const; // display all cow data 
}; 

方法實現:

// cow.cpp -- Cow class methods implementation (compile with main.cpp) 

#include <cstring> 
#include <iostream> 
#include "cow.h" 

Cow::Cow() // default destructor 
{ 
    strcpy(name, "empty"); 
    hobby = new char[6]; // makes it compatible with delete[] 
    strcpy(hobby, "empty"); 
    weight = 0.0; 
} 

Cow::Cow(const char *nm, const char *ho, double wt) 
{ 
    strcpy(name, nm); // name = nm; is wrong, it copies the address of the argument pointer (swallow copying) 
    /*if (name[20] != '\0') // if it's not a string, make it a string (in case nm is larger than 20) 
     name[20] = '\0';*/ 
    hobby = new char[strlen(ho) + 1]; // allocates the needed memory to hold the argument string 
    strcpy(hobby, ho); // copies the pointed-to data from the argument pointer to the class pointer 
    weight = wt; 
} 

Cow::Cow(const Cow &c) // copy constructor 
{ 
    strcpy(name, c.name); // copies the value to the desired address 
    char *temp = hobby; // stores the address of the memory previously allocated with new 
    hobby = new char[strlen(c.hobby) + 1]; 
    strcpy(hobby, c.hobby); // copies the value to the new address 
    delete[] temp; // deletes the previously new allocated memory 
    weight = c.weight; 
} 

Cow::~Cow() 
{ 
    delete[] hobby; 
} 

Cow & Cow::operator=(const Cow &c) // overloaded assignment operator 
{ 
    strcpy(name, c.name); 
    char *temp = hobby; 
    hobby = new char[strlen(c.hobby) + 1]; 
    strcpy(hobby, c.hobby); 
    delete[] temp; 
    weight = c.weight; 
    return *this; 
} 

void Cow::ShowCow() const 
{ 
    std::cout << "Name: " << name << '\n'; 
    std::cout << "Hobby: " << hobby << '\n'; 
    std::cout << "Weight: " << weight << "\n\n"; 
} 

客戶:

// main.cpp -- Exercising the Cow class (compile with cow.cpp) 

#include "cow.h" 
#include <iostream> 

int main() 
{ 
    using std::cout; 
    using std::cin; 

    Cow subject1; // default constructor 
    Cow subject2("Maria", "Reading", 120); // non-default constructor 
    Cow subject3("Lula", "Cinema", 135); 
    subject1 = subject3; // overloaded assignment operator 
    Cow subject4 = subject2; // copy constructor 
    subject1.ShowCow(); 
    subject2.ShowCow(); 
    subject3.ShowCow(); 
    subject4.ShowCow(); 

    cin.get(); 
    return 0; 
} 

我躲在一些地方的代碼查找可能出現的問題,它似乎在編程'不喜歡這兩條線:

subject1 = subject3; 
Cow subject4 = subject2 

,特別是,在重載賦值操作符和拷貝構造函數,如果我隱藏delete[] temp線,程序不會崩潰。

我總是noob,可能是一些愚蠢的,但我不明白我在做這些定義錯誤。

任何幫助?

+1

在C++中,您通常不會編寫這樣的賦值運算符,因爲它們與複製構造函數非常相似,因此大多數代碼重複。我建議看看[Copy and swap idiom](http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Copy-and-swap) – dialer

+0

@dialer感謝您的建議!現在我正在用一個真正結構化的逐片方法來跟蹤一本書。但我會看看。 – Kurospidey

回答

3
Cow::Cow(const Cow &c) // copy constructor 
{ 
    strcpy(name, c.name); // copies the value to the desired address 
    char *temp = hobby; // stores the address of the memory previously allocated with new 
    hobby = new char[strlen(c.hobby) + 1]; 
    strcpy(hobby, c.hobby); // copies the value to the new address 
    delete[] temp; // deletes the previously new allocated memory 
    weight = c.weight; 
} 

這是複製c-tor。沒有以前分配的成員。 this->hobby指向隨機垃圾。所以當你delete[] temp(即新作業之前的this->hobby),你會得到UB。

Cow & Cow::operator=(const Cow &c) // overloaded assignment operator 
{ 
    strcpy(name, c.name); 
    char *temp = hobby; 
    hobby = new char[strlen(c.hobby) + 1]; 
    strcpy(hobby, c.hobby); 
    delete[] temp; 
    hobby = name; 
    weight = c.weight; 
    return *this; 
} 

hobby = name是不正確的,因爲它會導致內存泄漏+析構函數會嘗試刪除未用operator new[]分配的對象。

+0

感謝您的幫助!確實是一個真正的noob錯誤,嘗試構造函數就好像它是一個賦值運算符。第二個錯誤是我破解我添加的代碼的錯誤之一,該行不應該在那裏。謝謝你的時間! – Kurospidey

0

@ForEveR已經注意到您的拷貝構造函數正在刪除從未分配過的內存。

但是我要說的是,整個練習是有缺陷的,並且正在用類C而不是C++教學。如果你使用了字符串,你所有的問題都會消失,因爲你不需要直接管理資源。這消除了你完全編寫析構函數或複製賦值/構造函數的需要。例如:

class Cow 
{ 
    std::string name; 
    std::string hobby; 
    double weight; 
public: 
    Cow(); 
    Cow(const std::string& nm, const std::string& ho, double wt); 
    void ShowCow() const; // display all cow data 
}; 
+0

謝謝你的回答。事情是作者已經知道了。實際上,之前的一個練習涉及創建一個StringBad類來模擬(以簡化的方式)標準字符串行爲。我知道字符串這一切都沒有了,但它只是專門實踐類的動態內存分配。 – Kurospidey

相關問題