2012-12-19 102 views
2

的瓦楞紙自己的容器的析構函數的char *成員,直到然後我用來應付,在這裏我試圖建立我自己的容器類使用向量。我需要它爲我的工作。我使用代碼塊10.05崩潰,如果刪除使用矢量

class myclass 
{ 
    public : 
     vector<myclass> array; 
     char * classname; 
     ... 

的問題是,我的我的類數據如果刪除不析構函數發生的以及顯示在屏幕上。如果我刪除classname,我的函數show()將顯示奇數字符。我認爲它來自我的方法來建立對象和範圍的問題,當我通過他們作爲參數。

myclass::~myclass() 
{ 
    //if(classname) delete [] classname; 
} 

這是它是如何在初始化的構造函數:

myclass::myclass(long lvl = 0, const char name[] = "undefined") 
    :ID(++ ID_counter) 
    { 
     level = lvl; 

     int namelength = strlen(name); 
     classname = new char[namelength + 1]; 
     strcpy(classname, name); 
    } 

add_content(常量MyClass的& C)應該使c.array考覈的元素的副本, 「push_back」他們在this-> array 我發現每個機會我們可以把一個沒有名字的對象作爲參數:mycontainer.add_content(myclass(3,5)); 它的工作原理,但我懷疑有關的範圍應該有

> int main() 
>  { 
>  myclass mycontainer(0); 
>  mycontainer.add_content(myclass(3,5)); 
>  ... 

這裏是的全碼:

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

class myclass 
{ 
    public : 

    vector<myclass> array; 
    static long ID_counter; 
    long ID; 
    long level; 
    char * classname; 

    myclass(int n, long lvl, const char name[]); //push_back n elements, lvl = 0, name = "undefined" 
    myclass(long lvl, const char name[]); //lvl = 0, name = "undefined" 
    myclass::~myclass(); 

    void set_level(long lvl); //recursive function, go down the tree 
    void add(int n); //push_back n elements 
    void add(const myclass & c); //push_back and set back the levels 
    void add_content(const myclass & c); //push_back all the c.array[i] and set back the levels 

    void show(); 

    template <typename T> myclass & operator[](const T it){ return array[it]; } 
}; 

long myclass::ID_counter = 0; 

myclass::myclass(long lvl = 0, const char name[] = "undefined") 
:ID(++ ID_counter) 
{ 
    level = lvl; 

    int namelength = strlen(name); 
    classname = new char[namelength + 1]; 
    strcpy(classname, name); 
} 
myclass::myclass(int n, long lvl, const char name[] = "undefined") 
:ID(++ ID_counter) 
{ 
    level = lvl; 

    int namelength = strlen(name); 
    classname = new char[namelength + 1]; 
    strcpy(classname, name); 

    for(int i = 0; i < n; i++) array.push_back(myclass(this->level + 1)); 
} 
myclass::~myclass() 
{ 
    //if(classname) delete [] classname; //there is the point ! 
} 

void myclass::add(int n = 1) 
{ 
    for(int i = 0; i < n; i++) array.push_back(myclass(level + 1)); 
} 

void myclass::add(const myclass & c) 
{ 
    array.push_back(c); 
    array[array.size() - 1].set_level(level + 1); 
} 

void myclass::add_content(const myclass & c) 
{ 
    for(int i = 0; i < c.array.size(); i++) 
    { 
     array.push_back(c.array[i]); 
     array[array.size() - 1].set_level(level + 1); 
    } 
} 

void myclass::set_level(long lvl) 
{ 
    level = lvl; 
    for(int i = 0; i < array.size(); i++) array[i].set_level(level + 1); 
} 

void myclass::show() 
{ 
    cout << "ID : " << ID << "\tLvl : " << level << "\t Classname : " << classname << endl; 
} 

int main() 
{ 
    myclass mycontainer(0); //ground level 
    mycontainer.add_content(myclass(3,5)); //the 3 elements level 5 should be reset to 0+1 

    mycontainer.show(); 

    for(int i = 0; i < mycontainer.array.size(); i++) 
    { 
     mycontainer[i].show(); 

     for(int j= 0; j < mycontainer[i].array.size(); j++) 
     mycontainer[i][j].show(); 
    } 
    cout << "\ncheckpoint\n"; 
    system("PAUSE"); //press any key to crash! 
    return 0; 
} 

這裏在析構函數沒有刪除*類名中,程序發現這個:

ID : 1 Lvl : 0 Classname : undefined 
ID : 3 Lvl : 1 Classname : undefined 
ID : 4 Lvl : 1 Classname : undefined 
ID : 5 Lvl : 1 Classname : undefined 

checkpoint 
Appuyez sur une touche pour continuer... 

與缺失和一些不好的字符顯示了一個崩潰:

ID : 1 Lvl : 0 Classname : undefined 
ID : 3 Lvl : 1 Classname : ░(? 
ID : 4 Lvl : 1 Classname : ░(? 
ID : 5 Lvl : 1 Classname : ░(? 

checkpoint 
Appuyez sur une touche pour continuer... 

Process returned -1073741819 (0xC0000005) execution time : 29.651 s 
Press any key to continue. 

我想回去學習有關參數和指針的一些原則,但這種語言是太經驗和沒有意義的。感謝您的幫助。

+5

也許對[The Rule of Three](http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming))的評論可能揭示這一點,特別是對'myclass'(如果這不明顯)。 – WhozCraig

回答

7

你有一個原始指針,沒有定義一個拷貝構造函數或賦值操作符。這意味着你得到了自動生成的版本,這是你不想要的。回顧三條法則。

解決方案#1:實現適當的拷貝構造函數和賦值運算符。

解決方案#2:將char * classname更改爲std::string classname。現在自動生成的拷貝構造函數和賦值操作符將工作。增加的好處:您不需要使用new,您不需要使用delete

+1

+1我選擇解決方案#2,以及使保護或私有的構造函數中的至少一個。 – WhozCraig

1

您應該定義複製構造函數。

我這裏調試器會引發錯誤:

for(int i = 0; i < n; i++) array.push_back(myclass(this->level + 1)); 

我們在這裏看到,所創建的新myclass對象,然後將其複製(克隆)爲array,那麼任何局部變量確實原來被破壞。

因此,我們必須使用同一指針的兩個實例:一個打掉一個內部array,默認的拷貝構造函數,其副本只是原始內存中創建。因此,實例內部array是無效的,因爲析構函數已經跑就可以了。

守則

以下額外的構造將解決情況:

myclass::myclass(const myclass& other) 
:ID(++ ID_counter) 
{ 
    level = other.level; 

    int namelength = strlen(other.classname); 
    classname = new char[namelength + 1]; 
    strcpy(classname, other.classname); 
} 

(以上是所謂的「拷貝構造函數」是的,當然你還是應該遵從「三法則「以避免所有潛在的錯誤)