简体   繁体   English

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

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

I'm currently working on new project with my team in Cpp and we decide to say good bye to the old fashioned raw pointers and give the smart pointers a try. 我正在与我在Cpp的团队一起开展新项目,我们决定对老式的原始指针说再见,并试一试智能指针。

I'm really new at this world and decided to try a few things that I'll need for our project before use them for real. 我在这个世界上真的很陌生,决定尝试一些我需要的项目,然后才能真正使用它们。

The thing is, I started with the basics, and then I've got stucked with this. 问题是,我从基础知识开始,然后我就一直坚持这一点。

When I create two new (shared) pointers (see the code below) with the make_shared function, and then (cross) store them in the other's inner vector, neither of them get destroyed at the end of the program. 当我使用make_shared函数创建两个新的(共享)指针(请参阅下面的代码),然后(交叉)将它们存储在另一个内部向量中时,它们都不会在程序结束时被销毁。

shared_ptr.cpp: 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));

}

compiler instructions 编译指令

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

My question here is, shouldn't the shared pointer handle the reference itself? 我的问题是,共享指针不应该处理引用本身吗? Or should I be the one to clear the inside-vector before the program finished? 或者我应该在程序结束前清除内部向量?

Maybe I just have to store raw pointers in the inner lists and just stick to the smart pointers in those sections where I do create and delete them. 也许我只需要在内部列表中存储原始指针,并在我创建和删除它们的那些部分中坚持使用智能指针。

I have to use a similar structure in my project, that's why I wanted to ask here first before frustrating and going back to the old (but effective) raw pointer. 我必须在我的项目中使用类似的结构,这就是为什么我想在遇到令人沮丧并回到旧的(但有效的)原始指针之前先问这里。

Thanks! 谢谢!

Shared pointers are reference counted pointers. 共享指针是引用计数指针。

They are not "garbage collected pointers" and cannot be used arbitrarily as such. 它们不是“垃圾收集指针”,不能任意使用。 Specifically, reference counting cannot handle cyclic references: if A points to data that points to B's data and B points to data that points to A's data then if A goes out of scope A's content will not be destroyed because B still refers to it and if B then goes out of scope B's content will not be destroyed because A still refers to it. 具体来说,引用计数不能处理循环引用:如果A指向指向B数据的数据而B指向指向A数据的数据,那么如果A超出范围A,则内容不会被销毁,因为B仍然引用它,如果B然后超出范围B的内容不会被销毁,因为A仍然引用它。

Shared pointers model the common sense notion of shared "ownership", if A uniquely refers to B using a shared pointer, one can think of A as owning B. If A and C both refer to B with shared pointers then we can think of A and C as jointly owning B. If your data does not conform to a notion of ownership like this then you should not use shared pointers. 共享指针模拟共享“所有权”的常识概念,如果A使用共享指针唯一引用B,则可以将A视为拥有B.如果A和C都使用共享指针引用B,那么我们可以想到A和C一起拥有B.如果你的数据不符合这样的所有权概念那么你就不应该使用共享指针。 In particular in generic directed graphs, individual vertices cannot be said to "own" their neighbors as generic graphs can have arbitrary topologies; 特别是在通用有向图中,不能说各个顶点“拥有”它们的邻居,因为通用图可以具有任意拓扑; they exhibit no natural hierarchy; 他们没有自然的等级; there are no "parents" and "children" in arbitrary graphs. 在任意图中没有“父母”和“孩子”。 That is, such graphs can have cycles. 也就是说,这样的图可以具有循环。

Directed acyclic graphs are a different story: their vertices can be ordered in what is called a " topological order " in which parents precede children. 有向无环图是一个不同的故事:它们的顶点可以在所谓的“ 拓扑顺序 ”中排序 ,其中父母在子节点之前。 There is a sense in which groups of vertices do own other vertices. 有一种感觉,顶点组确实拥有其他顶点。

This is not to say that there is no way to manage the memory allocated by the vertices of a general graph using smart pointers, just that you can't do it by treating its vertices as the shared owners of child vertices. 这并不是说没有办法使用智能指针来管理由一般图形的顶点分配的内存,只是你不能通过将其顶点视为子顶点的共享所有者来做到这一点。 You could for example create vertices with a factory that maintains references to what it creates as a collection of std::unique_ptrs and use raw pointers for references from vertex to vertex. 例如,您可以使用工厂创建顶点,该工厂维护对作为std :: unique_ptrs集合创建的内容的引用,并使用原始指针进行从顶点到顶点的引用。 Or you could maintain your graph as a DAG of shared_ptrs but use weak_ptrs for the "back pointers" from children to parents. 或者您可以将图形维护为shared_ptrs的DAG,但使用weak_ptrs作为从子项到父项的“后向指针”。

What design is the best depends on the specifics of what you are doing. 什么样的设计是最好的取决于你正在做什么的细节。

My question here is, shouldn't the shared pointer handle the reference itself? 我的问题是,共享指针不应该处理引用本身吗? Or should I be the one to clear the inside-vector before the program finished? 或者我应该在程序结束前清除内部向量?

There are many solutions to that. 有很多解决方案。 Of course, a std::weak_ptr can break the cycle, but sometimes it's another issue. 当然, std::weak_ptr可以打破循环,但有时候这是另一个问题。

Take this for example: 以此为例:

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

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

Yes, indeed, each node have reference to other node. 是的,确实,每个节点都引用了其他节点。 And we don't want dangling, so shared it is... no? 而且我们不想悬空,所以分享它是......不是吗?

No. clearly here, we have a owner of all nodes: the Graph class. 清楚这里,我们拥有所有节点的所有者: Graph类。

If we write the same code with Graph being the unique owner of the nodes, we get this: 如果我们使用Graph作为节点的唯一所有者编写相同的代码,我们得到:

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

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

When the graph dies, it takes to nodes with it. 当图形消亡时,它会带有节点。

Buuuuuut! Buuuuuut! What happens when I do this: 当我这样做时会发生什么:

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

Well, you broke the contract. 好吧,你打破了合同。 Does it really make sense to have a node without a graph? 拥有一个没有图形的节点真的有意义吗?

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

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