繁体   English   中英

存储在共享指针(Shareption)中的另一个对象内的智能指针向量中存储的共享指针

[英]Shared pointers stored in a smart pointer vector inside another object stored in a shared pointer (Shareption)

我正在与我在Cpp的团队一起开展新项目,我们决定对老式的原始指针说再见,并试一试智能指针。

我在这个世界上真的很陌生,决定尝试一些我需要的项目,然后才能真正使用它们。

问题是,我从基础知识开始,然后我就一直坚持这一点。

当我使用make_shared函数创建两个新的(共享)指针(请参阅下面的代码),然后(交叉)将它们存储在另一个内部向量中时,它们都不会在程序结束时被销毁。

shared_ptr.cpp:

#include <iostream>
#include <memory>
#include <vector>
#include <string>

using namespace std;

class Object{

public:

    vector<shared_ptr<Object>> list;
    string name;
    Object(string name){
        this->name=name;
    }
    ~Object(){
        cout<<"...Deleting "<<name<<endl;
    }
};

int main(){

    shared_ptr<Object> o1 = make_shared<Object>("o1");
    shared_ptr<Object> o2 = make_shared<Object>("o2");

    o1->list.push_back(shared_ptr<Object>(o2));
    o2->list.push_back(shared_ptr<Object>(o1));

}

编译指令

g++ shared_ptr.cpp -o shared.o && ./shared.o

我的问题是,共享指针不应该处理引用本身吗? 或者我应该在程序结束前清除内部向量?

也许我只需要在内部列表中存储原始指针,并在我创建和删除它们的那些部分中坚持使用智能指针。

我必须在我的项目中使用类似的结构,这就是为什么我想在遇到令人沮丧并回到旧的(但有效的)原始指针之前先问这里。

谢谢!

共享指针是引用计数指针。

它们不是“垃圾收集指针”,不能任意使用。 具体来说,引用计数不能处理循环引用:如果A指向指向B数据的数据而B指向指向A数据的数据,那么如果A超出范围A,则内容不会被销毁,因为B仍然引用它,如果B然后超出范围B的内容不会被销毁,因为A仍然引用它。

共享指针模拟共享“所有权”的常识概念,如果A使用共享指针唯一引用B,则可以将A视为拥有B.如果A和C都使用共享指针引用B,那么我们可以想到A和C一起拥有B.如果你的数据不符合这样的所有权概念那么你就不应该使用共享指针。 特别是在通用有向图中,不能说各个顶点“拥有”它们的邻居,因为通用图可以具有任意拓扑; 他们没有自然的等级; 在任意图中没有“父母”和“孩子”。 也就是说,这样的图可以具有循环。

有向无环图是一个不同的故事:它们的顶点可以在所谓的“ 拓扑顺序 ”中排序 ,其中父母在子节点之前。 有一种感觉,顶点组确实拥有其他顶点。

这并不是说没有办法使用智能指针来管理由一般图形的顶点分配的内存,只是你不能通过将其顶点视为子顶点的共享所有者来做到这一点。 例如,您可以使用工厂创建顶点,该工厂维护对作为std :: unique_ptrs集合创建的内容的引用,并使用原始指针进行从顶点到顶点的引用。 或者您可以将图形维护为shared_ptrs的DAG,但使用weak_ptrs作为从子项到父项的“后向指针”。

什么样的设计是最好的取决于你正在做什么的细节。

我的问题是,共享指针不应该处理引用本身吗? 或者我应该在程序结束前清除内部向量?

有很多解决方案。 当然, std::weak_ptr可以打破循环,但有时候这是另一个问题。

以此为例:

struct Graph {
    struct Node {
        std::array<std::shared_ptr<Node>, 4> adjacent;
    };

    std::vector<std::shared_ptr<Node>> nodes;
};

是的,确实,每个节点都引用了其他节点。 而且我们不想悬空,所以分享它是......不是吗?

清楚这里,我们拥有所有节点的所有者: Graph类。

如果我们使用Graph作为节点的唯一所有者编写相同的代码,我们得到:

struct Graph {
    struct Node {
        std::array<Node*, 4> adjacent;
    };

    std::vector<std::unique_ptr<Node>> nodes;
};

当图形消亡时,它会带有节点。

Buuuuuut! 当我这样做时会发生什么:

 Node n = *get_graph_copy().nodes[1]; n.adjacent[0]; // boom! 

好吧,你打破了合同。 拥有一个没有图形的节点真的有意义吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM