【问题标题】:Create shared objects in container using STL使用 STL 在容器中创建共享对象
【发布时间】:2021-11-08 21:47:04
【问题描述】:

我正在尝试生成一个包含共享对象的容器。 比如说,两个有几个公共节点的链表。

L1 : {1 2 3 2 1} 和 L2 : {2 1}

我知道如果我们使用 Node* 头并将动态创建的对象添加为链接,那么可以在两个链表中链接公共对象,但是可以直接在容器中创建这样的共享对象吗?

我正在尝试这样的事情:

std::forward_list<int> listOne{1,2,3,2,1}; // 2,1 are meant to be shared
std::forward_list<int> listTwo{1};
listTwo.insert_after(listTwo.begin(), 
std::next(listOne.begin(), 3), listOne.end()); // taking 2,1 from listOne

但是,这只会创建另一个新分配。

我假设这可能由于迭代器失效场景等而被禁止,产生异常行为,但我不确定。有没有其他办法?

【问题讨论】:

  • 这是不可能的。您不能(重新)链接链表的节点,这只是链表的业务。
  • 也许std::shared_ptr 是您要找的?
  • @Evg 一个 DSA 问题是在一个链表中找到相交的节点,节点的地址应该是公共的。就像我说的,它可以使用 Node* head 来完成,但是我必须手动创建一个容器类,只是为了这个操作。还有其他更好的方法吗?
  • std::vector&lt;std::shared_ptr&lt;int&gt;&gt; 怎么样?
  • @ppadhy 标准库容器拥有它们存储的对象,所以不,您不能共享列表的某些部分。一些恶作剧可以用std::setstd::map(以及其他关联容器)来完成,因为它暴露了自 C++17 以来的部分内部结构,但即使这样也不是用于手动指针重新布线,仅用于复制-地图之间的移动节点更少。

标签: c++ stl


【解决方案1】:

您可以使用std::shared_ptr,因为无论指向同一对象的另一个std::shared_ptr 是否从不同的容器中删除,这都会使其对象保持活动状态。

容器类型对此并不重要,因此您可以使用std::vector 例如:

    std::vector<std::shared_ptr<int>> v1
    {
        std::make_shared<int>(1),
        std::make_shared<int>(2),
        std::make_shared<int>(3),
        std::make_shared<int>(2),
        std::make_shared<int>(1),
    };

    std::vector<std::shared_ptr<int>> v2
    {
        v1[3],
        v1[4],
    };

    std::cout << "v1" << '\n';
    for(auto& sp: v1)
        std::cout << *sp << '\n';

    std::cout << "v2" << '\n';
    for(auto& sp: v2)
        std::cout << *sp << '\n';

    v1.pop_back(); // remove from one container but
    v1.pop_back(); // still alive and kicking in the other 
    std::cout << "----" << '\n';

    std::cout << "v1" << '\n';
    for(auto& sp: v1)
        std::cout << *sp << '\n';

    std::cout << "v2" << '\n';
    for(auto& sp: v2)
        std::cout << *sp << '\n';

输出:

v1
1
2
3
2
1
v2
2
1
----
v1
1
2
3
v2
2
1

【讨论】:

    【解决方案2】:

    您可以为此创建一个共享指针列表。

    std::list<int> listInt {1,2,3,2,1};
    
    std::list<std::shared_ptr<int>> listOne{};
    std::list<std::shared_ptr<int>> listTwo{};
    
    size_t counter = 0;
    for(int elem : listInt)
    {
        auto ptr1 = std::make_shared<int>(elem);
        listOne.push_back(ptr1);
        if(counter < 3)
            listTwo.push_back(std::make_shared<int>(elem));
        else
            listTwo.push_back(ptr1);
        counter++;
    }
    

    【讨论】:

    • 你可以,但你应该详细说明你想要这样做的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-08
    • 1970-01-01
    • 1970-01-01
    • 2013-03-06
    • 1970-01-01
    • 2012-07-02
    相关资源
    最近更新 更多