2017-01-25 4 views
1

に動的なオブジェクトのリストを作成することができ、私はアイデアは、ネストされたリストのリストを作成することであるC++はどのように私はC++

#include <iostream> 
#include <string> 
#include <list> 
using namespace std; 

class test { 
    private: 
     string _name; 
     list<test*> _list; 
    public: 
     test(const string& S): _name(S) { this->_list.clear(); } 

     const string& to_string() { 
      string*sp = new string("["); 
      *sp += this->_name; 
      for(test*tp: this->_list) { 
       *sp += ","; 
       *sp += tp->to_string(); 
      } 
      *sp += "]"; 
      return *sp; 
     } 

     test& add(const string& S) { 
      test*tp = new test(S); 
      this->_list.push_back(tp); 
      return *tp; 
     } 
}; 

int main() { 
    test x("one"); 
    x.add("two"); 
    test y = x.add("three"); 
    y.add("four"); 
    cout << y.to_string() << '\n'; 
    cout << x.to_string() << '\n'; 
} 

に、この単純なプログラムを持っています。 yは私はyを変更する場合しかし、その後xが変更されない、xの要素であると考えられます。

所望の出力は次のようになります。

[three,[four]] 
[one,[two],[three,[four]]] 

が、私は

[three,[four]] 
[one,[two],[three]] 

を取得し、私はおそらくtest::addにポインタを返すとmainを変更することで問題を解決することができます

int main() { 
    test x("one"); 
    x.add("two"); 
    test*p = x.add("three"); 
    p->add("four"); 
    cout << y->to_string() << '\n'; 
    cout << x.to_string() << '\n'; 
} 

しかし、 。タイプtestではなく、タイプtest*としてpとしてy使用する方法はありますか?

+1

コピーコンストラクタがリストをクリアするのはなぜですか? –

+3

私はたくさんの(本当に不必要な) '新しい'を見ますが、 '削除'はありません。 'y'が' x'に影響を与えたいのであれば、必要なのは新しいオブジェクトではなく参照だけです。 – chris

答えて

2

あなたは「3」のコピーを作成し、それを「4」を追加しました。あなたが好き行うことができます

test y = x.add("three"); 

:ところで

test& y = x.add("three"); 

、あなたのコードは、メモリリークを作成します。仮想デストラクタを書き込みます。

1

はい、あなただけのxとの関係を維持するためにytest&を行うことができます。

Live Example

1

あなたが動的にヒープに割り当てられたオブジェクトの多くを使用しているように見えます。適切なクリーンアップのために、代わりに生所有ポインタ(std::shared_ptrのような)スマートポインタの使用を検討し、リークを避けるために。

私はこれに多くの時間を費やしたが、あなたの最初のコードを取得し、スマートポインタ(およびstd::vectorstd::listでいくつかの生のポインタの使用を交換していない、あなたはそのイテレータの無効化プロパティのlistをしたいですかしない限り、std::vectorがする傾向があります

出力:

[three,[four]] 
[one,[two],[three,[four]]] 
0123より良いオプションが)、私が働くようで、このコード( live sample)を得ました

出典:別の方法として

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

class Test { 
private: 
    string _name; 
    vector<shared_ptr<Test>> _list; 
public: 
    explicit Test(const string& S) : _name(S) { } 

    string to_string() const { 
     string s("["); 
     s += _name; 

     for (auto const& p : _list) { 
      s += ","; 
      s += p->to_string(); 
     } 

     s += "]"; 
     return s; 
    } 

    shared_ptr<Test> add(const string& S) { 
     auto p = make_shared<Test>(S); 
     _list.push_back(p); 
     return p; 
    } 
}; 

int main() { 
    auto x = make_shared<Test>("one"); 
    x->add("two"); 
    auto y = x->add("three"); 
    y->add("four"); 

    cout << y->to_string() << '\n'; 
    cout << x->to_string() << '\n'; 
} 

、それはあなたの特定の設計のために理にかなっている場合、あなたはまた、代わりに(スマート)ポインタのtest::addからあなたのオブジェクトへの参照(T&)を返す考慮し、unique_ptrを使用することができます_listベクトルデータメンバーと(代わりshared_ptrの)。これは一種の代替バージョン(live)です:

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

class Test { 
private: 
    string _name; 
    vector<unique_ptr<Test>> _list; 
public: 
    explicit Test(const string& S) : _name(S) { } 

    string to_string() const { 
     string s("["); 
     s += _name; 

     for (auto const& p : _list) { 
      s += ","; 
      s += p->to_string(); 
     } 

     s += "]"; 
     return s; 
    } 

    Test& add(const string& S) { 
     _list.push_back(make_unique<Test>(S)); 
     return *(_list.back()); 
    } 
}; 

int main() { 
    Test x("one"); 
    x.add("two"); 
    Test& y = x.add("three"); 
    y.add("four"); 

    cout << y.to_string() << '\n'; 
    cout << x.to_string() << '\n'; 
}