2016-05-04 10 views
0

私は、このツリー構造を持っている:C++デストラクタ

public: 
    node(string& const n); 
    virtual ~node(); 
    string get_name() const; 
    void set_name(string& new_name); 
    int get_nr_children() const; 
    node get_child(int i) const; 
    void add_child(node child); 
private: 
    string& name; 
    vector<node> children; 
}; 

と私のmain.cppには、次のようになります。

int main() { 
    string s = "root"; 
    node r(s); 
    string s2 = "left child"; 
    node ls(s2); 
    string s3 = "right child"; 
    node rs(s3); 

    r.add_child(ls); 
    r.add_child(rs); 

    r.~node(); 
} 

(私は~node()がでとにかくすべてのオブジェクト上で実行されていることを知っていますmain funcitonの終わりですが、最初にルートrで実行されていることを確認します)

すべてのメソッドはこれまでうまくいきますeデストラクタ。これは私の最初のデストラクタであり、次の再帰的なtryを思いついたが、なぜうまくいかないのか分からない。

node::~node() { 
    cout << "Enter ~node of " << this->get_name() << endl; 
    while (this->get_nr_children() != 0) { 
     this->get_child(0).~node(); 
     this->children.pop_back(); 
    } 
    delete this; 
    cout << "Leave ~node of " << this->get_name() << endl; 
} 

結果は「左の子の〜ノードを入力します」

+2

_'lele this; '_hh?それはまったく間違っている! –

+3

デストラクタを直接呼び出しません*。代わりに 'delete'を使用してください(より良いことに、コンテナまたはスマートポインタを使用する方が良い)。 – crashmstr

+1

'add_child'が私たちが提供できるのは投機です。 [mcve]を作る。また、 'delete'の直後に' this'にアクセスします。 – nwp

答えて

1

の無限の出力である、それはコンパイルする場合、これは無効と歩留まり未定義の動作です。このデータの時点で

vector<node> children; 

メンバ宣言クラスnode不完全です;そのサイズはまだ分かっていません。

標準ライブラリコンテナの項目タイプとして不完全な型を使用することはできませんが、ポインタを使用することはできます。デストラクタの実装で


、また

delete this; 

、ように自分自身を呼び出し、(このdelete式で)デストラクタを呼び出す無限の再帰を未定義の動作が得られます。


データメンバ宣言

string& name; 

もそれについての強い、不快な臭いを持っていますが、あなたは、コンストラクタの実装を示していないので、私はそれが間違っていることを断固として100%を述べることはできません。

ただし、コードの残りの部分が与えられている場合、これが正しいとする機会は無限小です。ただ、「(私は〜ノードは、()メインfuncitonの終わりにとにかくすべてのオブジェクト上で実行されていることを知っているが、私はそれが最初のルートR上で実行されていることを確認したい)」

string name_; 
+0

最初のものはC++ 1zで許可されています。 –

+0

@ T.C。あなたは、C++でサポートされる可能性が最も高いことを意味します。ありがとう、私は知らなかった。あなたはリファレンスがありますか? –

+0

http://eel.is/c++draft/vector#vector.overview-3 –

3

を使用

この見積もりは、この質問のすべてが誤解に基づいていると言えるくらい十分です。

修正しようとしても意味がありません。完全な書き換えが必要です。

代わりに、destrcuctors、その呼び出し、およびそれらが何であるかについての詳細を読んでください。

明示的に呼び出しても、暗黙の呼び出しが抑制されるわけではありません。そして、二重破壊は未定義の振る舞いです。

また、delete thisは非常にトリッキーなものですが、それは何を意味するかを非常に確かめる必要があります。

クラスメソッド(this->...)にアクセスしたり、データを削除してアクセスしたりすると、問題が発生するだけです。

1

通常、ツリーはフリーストアに割り当てられたノードを使用します。これは、ノードへのポインタのトラフィッキングと、もはや使用されていないノードの削除を意味します。問題のコードは、そのモデルに従っていません。スタック上にルートノードを割り当て、各ノード内にポインタではなくノードオブジェクトを格納します。そのコードでは、コンパイラによって生成されたすべてのデストラクタはうまく動作します。ユーザー定義のデストラクタは必要ありません。

関連する問題