2016-09-02 12 views
1

C++のコーディングを行ってからしばらくして、基本リンクリストのどの変数がデストラクタで削除されるべきか不思議でした。私のC++のハンドブックは現時点で問題について相談していません。次のようにリンクリストクラスが見えます:クラスのデストラクタですべて削除する必要があるもの

#include <string> 
#include <vector> 

class Node 
{ 
    Node *next; 
    string sName; 
    vector<char> cvStuff; 

    Node(string _s, int _i) 
    { 
     next = nullptr; 
     sName = _s; 

     for (int i = 0; i < _i; i++) 
     { 
      cvStuff.insert(cvStuff.end(), '_'); 
     } 
    } 

    ~Node() 
    { 
     //since sName is assigned during runtime do I delete? 
     //same for cvStuff? 
    } 
}; 

私は

delete next; 

呼び出すデストラクタでそれがリンクリストの次のノードに移動し、そのノードを削除します場合、私は、また好奇心としたがってその種の再帰的にその点からリスト全体を削除する?また、それが事実であり、何らかの理由でそれを実装することを選択した場合、削除する前にnextがnullptrであるかどうかを確認する必要がありますか、それとも違いはありませんか?

ありがとうございます。

+1

これは、ListNodeとListの両方であることを試みます。誰がリストを所有していますか?あなたが同じものであればリストの末尾を共有しますか?要素を削除するか、リスト全体を削除する予定ですか? – lorro

+0

@lorro、はいこれは技術的にノードクラスであり、それに応じて調整されています。共有テールを定義しますか?また、リスト全体を削除してください。この場合は –

+0

を削除しないでください!そうしないと、リストの任意の要素を消去するクイック消去を書き込むことができなくなります。フォワードリンクリストの末尾を共有するということは、2つのリストが同じ要素を背表に持つ必要があることを考えれば、ノードを共有するということです。一度構築されconstになるリストで非常に便利です。 – lorro

答えて

1

理想的には、何も:std::unique_ptr<>は、std::smart_ptr<>は、boost::scoped_ptr<>は、など。

そうでない場合は、あなたが所有しているネイティブポインタ何削除:スマートポインタを使用します。 nextは所有していますか?

  • リストの途中で何かを削除する予定ですか?はいの場合、デストラクタでは削除できません。
  • テールを共有する予定ですか?もしそうであれば、リファレンスカウントされたスマートポインタが必要です。

nullptr(何もしません)を削除しても問題ありません。この例では、sNameとcvStuffをスコープとして削除しないでください。自動的に破棄されます。

また、これが大きくなる可能性があるリストの場合は、&を手動で無効にして無効にすることができます。*nextこれは、再帰によってスタック領域を使いたくないためです。

さらに、これをデータ構造を意味するListと、要素を意味するListNodeに分けてください。あなたの質問は実際には、この曖昧さを示しています。デストラクタでListNodeまたはListを削除するかどうかは分かりません。それを分離することでこれが解決されます。

{ // scope 
    std::string s; 
} // end scope -> s.~string() 

deleteはそれで呼び出されない限り(newで割り当てられた)動的オブジェクトは、それがデストラクタが呼ばれていますがありません。

+0

私は次が所有しているかどうかわかりません。 1:機能について考える私は単一の要素を削除することは決してありませんが、リスト全体を削除するので、「再帰的なデストラクタ」部分全体について知りたいのです。 2:テールを共有することが何を意味するのか分かりません。単一のオブジェクトを指し示す複数のポインタがあるのでしょうか? 3:リストは6より大きいことはありませんが、スタック領域の不足による手動破壊に関しては、これらのノードを含むクラスで繰り返しノードを削除する場合のように手作業で行うことを想定していますか? 4:はい、クラスは "ノード" –

+0

と呼ばれる必要があります。1.あなたが消去したくない場合は、それはあなた次第です。私は、unique_ptr <>を強く考えています。そのようにしても、この選択をする必要はありません。 2.正確に - 共有する場合は、shared_ptr <>またはsgを使用します。同様の場合3.その場合、リストを忘れて要素ptrsの小さなベクトル(または可能であれば要素)を格納します。それとは別に、はい、私は繰り返しを意味しました。 4. ok;それでもまだ、私は削除する 'List'と(驚かない)' Node'を持つことをお勧めします - しかし、選択肢はオープンです。 – lorro

+0

アドバイスありがとうございます=) –

0

基本的に、あなただけの

delete next 

、それはあなたが何をすべきすべてです必要があります。

  • stringvectorオブジェクト自身のデストラクタを持っており、以来、このオブジェクトが破壊され、theirs will be called

  • Deleting a null pointer is not a problemですので、確認する必要はありません。

  • nextがヌルポインタでない場合、必要に応じて次のノードのデストラクタの呼び出しを継続します。

ただ削除してください。

+1

うーん、const非テールシェアリングリストの場合にのみ当てはまります。非constリストの場合は、次のものを削除することはできません。これは、要素O(1)の消去を禁止します。尾を共有するリストの場合、さらに悪いことになります。他のすべての要素を削除することになります。 – lorro

+1

@lorro再帰的なデータ構造の場合、実際には 'shared_ptr'のような参照カウントスマートポインタを使うべきです。他の何かが悪夢になるだろう。ノード共有のデータ構造ははるかに稀です。次回の質問でこれを言えるかもしれません。 –

+0

@AmiTavory:lorroは質問者ではありません –

0

クラスデストラクタが呼び出されます(空です)。次に、メンバオブジェクトのデストラクタが呼び出されます。

メンバーがオブジェクトでない場合、デストラクタは呼び出されません。あなたの例では

- List *next: pointer on List: no destructor called 
- string sName: string object: destructor called 
- vector<char> cvStuff: vector object: destructor called 

グッドニュース:あなたは何の関係もありません。デストラクタ宣言はここでも役に立たない。

デストラクタでnextを削除した場合、アイテムを削除するとリストの他のアイテムがすべて削除されます。

(あなたのListオブジェクトはむしろNodeと呼びます)。 Listは、作成した最初のノードが保持する、すべてのノードの連鎖結果です。

1

自動寿命を持つオブジェクトは、それがスコープの外に出たときに呼び出されるデストラクタのしています。

メンバ変数の場合、有効範囲はオブジェクトの有効期間です。特別なことは何も上記で

struct S { 
    std::string str_; 
    char* p_; 
}; 

int main() { // scope 
    { // scope 
     S s; 
    } // end scope -> s.~S() -> str_.~string() 
} 

p_に起こる:それは単純なスカラー型であるポインタですので、コードはそれへの自動何もしません。

あなたのリストクラスでは、あなたが覚えておかなければならない唯一のことは、あなたのnextメンバーです:それは "所有"ポインタかどうかを判断する必要があります。それが "所有"ポインタの場合は、デストラクタ内のオブジェクトに対してdeleteを呼び出す必要があります。

また、あなたが「RAII」を活用することができます(リソースaquisitionが初期化され)とポインタをラップし、あなたのためのdeleteを呼び出すデストラクタを提供するために、オブジェクトを使用します。

{ // scope 
    std::unique_ptr<Node> ptr = std::make_unique<Node>(args); 
} // end scope -> ptr.~unique_ptr() -> delete -> ~Node() 

unique_ptrは純粋ですもう1つの方法は、オブジェクトにshared_ptrが残っていないときに、基礎となるオブジェクトがdelete dになるようにref-countingを使用するshared_ptrです。

たとえば、あなたはどこか別の場所Node秒の実際のアドレスを保持している、場合は、あなたのnextポインタが非所有のポインタであることを考えるでしょう:上記の場合

std::vector<Node> nodes; 
populate(nodes); 

list.insert(&nodes[0]); 
list.insert(&nodes[1]); 
// ... 

ベクトルは、ノードを所有していますNodeはあなたのものではないので、Nodeデストラクタでdeleteを呼び出してはいけません。ここ

list.insert(new Node(0)); 
list.insert(new Node(1)); 

このユースケースでは、我々は削除コールするNode::~Nodeを必要とするか、または私たちは、リークを持っているので、リスト/ノードは、ノードへのポインタを持っている唯一のものです。

関連する問題