如何在C++中创建动态对象列表

How can I create a list of dynamic objects in C++

本文关键字:动态 对象 列表 创建 C++      更新时间:2023-10-16

>我有这个简单的程序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*

您创建了"三"的副本并向其添加了"四"。

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

你可以这样做:

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

顺便说一下,您的代码会产生内存泄漏。 编写虚拟析构函数。

是的,你可以把y作为一个test&来保持与x的关系:

现场示例

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

我没有花太多时间在这上面,但是使用您的初始代码并用智能指针替换一些原始指针用法(std::liststd::vector;除非您确实想要list其迭代器失效属性,std::vector往往是更好的选择),我得到了这段似乎有效的代码(实时示例):

输出:

[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&),而不是(智能)指针,并将unique_ptr(而不是shared_ptr)与_list矢量数据成员一起使用。这是一种替代版本(实时):

#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';
}