【问题标题】:How can I create a list of dynamic objects in C++如何在 C++ 中创建动态对象列表
【发布时间】:2017-06-11 02:45:58
【问题描述】:

我有这个简单的 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应该是x的一个元素,但是当我修改y时,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';
}

但是。有没有办法使用y 作为类型test 而不是p 作为类型test*?

【问题讨论】:

  • 除此之外,复制构造函数为什么要清空列表?
  • 我看到很多(真的没必要)news,但没有看到deletes。如果你想让y 影响x,那么你只需要一个引用,而不是新对象。

标签: c++ c++11 pointers return-by-reference


【解决方案1】:

您创建了“三”的副本并在其中添加了“四”。

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

你可以这样做:

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

顺便说一句,您的代码会造成内存泄漏。编写虚拟析构函数。

【讨论】:

    【解决方案2】:

    是的,您可以将y 设为test&amp; 以保持与x 的关系:

    Live Example

    【讨论】:

      【解决方案3】:

      您似乎正在使用大量在堆上动态分配的对象。考虑使用 smart 指针(如 std::shared_ptr)而不是原始 owning 指针,以进行适当的清理并避免泄漏。

      我并没有花太多时间在这上面,但是使用您的初始代码并用智能指针替换一些原始指针使用(以及将 std::list 替换为 std::vector;除非您确实想要 list 的迭代器失效属性, std::vector 往往是一个更好的选择),我得到了这个似乎可以工作的代码(live sample):

      输出:

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

      来源:

      #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&amp;),并使用 unique_ptr(而不是 @ 987654333@) 与 _list 矢量数据成员。这是一种替代版本(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';
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-03
        • 1970-01-01
        • 1970-01-01
        • 2013-11-10
        • 1970-01-01
        • 2014-08-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多