【问题标题】:Ensuring shared pointers within vector are pushed back properly [closed]确保向量内的共享指针被正确推回[关闭]
【发布时间】:2017-07-10 08:06:15
【问题描述】:

我可能在某些方面有这样的错误,这真的是我第一次特别处理共享指针。

我正在遍历一棵树。我的树由一个链表组成,其中一个共享指针向量表示每个节点的所有子节点。为了遍历,我(首先)尝试这样做:

//--------------------------------------------------------------
void setupMesh(){
    Mesh mesh;

    shared_ptr<Mesh> shared_mesh(&mesh);
    meshes.push_back(shared_mesh);

    checkChildren(root, &temp_mesh);
}

//--------------------------------------------------------------
void checkChildren(Node * temp_node, Mesh * temp_mesh){

    if(!temp_node->children.empty()){
        for(int i = 0; i < temp_node->children.size(); i++){
            if(i > 0){
                shared_ptr<Mesh> new_mesh(new Mesh);
                meshes.push_back(new_mesh);
            }

            temp_node = temp_node->children[0].get();
            checkChildren(temp_child, temp_mesh);
        }
    }  
}

我的树结构本身看起来不错,但更多的是我如何遍历它以及我如何跟踪指针的问题。它当前返回错误的访问错误。据我所知,我似乎正在插入一个指向临时对象、temp_node 和 temp_mesh 的指针。

为了简化我的想法:

遍历属于节点[0](根)的所有子节点。 对于每个孩子,对他们执行相同的循环。如果孩子是 child[0],继续将它的坐标添加到同一个 temp_mesh 对象,但如果它是另一个孩子,则创建一个新的网格来存储它,以及它的所有第一个孩子。 任何新的网格都应该有一个指针被推回网格矢量 (vector>)。

有没有人建议我如何更有效地做到这一点,或者我在处理内存中的这些指针时哪里出错了。

【问题讨论】:

  • 请把edit 改成minimal reproducible example,而不是(看起来像)你的完整代码——也就是说,删除不相关的代码,直到你得到最短的可读、可编译的代码,证明问题。
  • 希望现在就足够了!
  • (这是一个有争议的问题,因为有人回答了,但为了完整起见:)非常接近!添加一个示例 mainNodeMesh 的定义,其中包含 刚刚 足以复制问题。它需要是完整的——也就是说,如果我将您提供的代码复制/粘贴到我的编辑器中,它就会编译、运行并演示问题。我在第一条评论中链接的文章提供了比以往更好的描述。

标签: c++ pointers vector shared-ptr


【解决方案1】:

它当前返回错误的访问错误。

那么这就是您应该首先担心的问题。这是一个严重的错误。

据我所知,我正在插入一个指向临时对象、temp_node 和 temp_mesh 的指针。

这不是“临时”对象,这意味着一些不同的东西(为什么你一直在变量名中使用“temp”?),但你是对的:

shared_ptr<ofMesh> shared_mesh(&temp_mesh);

这会创建一个shared_ptr,它拥有指针&amp;temp_mesh,因此当没有更多shared_ptr 对象共享该指针的所有权时,它将删除它。

但是那个指针是一个自动变量(又名堆栈变量)的地址,它在块的末尾超出了范围。您不“拥有”该对象,该功能的块范围会自动管理它。如果您不拥有它,那么您不能将它的所有权交给shared_ptr,因为它不是您可以放弃的。

当作用域结束时,自动变量temp_mesh 将被自动销毁,但仍有shared_ptr 对象持有该指针,认为他们拥有它。当您尝试通过那些shared_ptr 对象访问对象时,您会在其生命周期结束后访问已销毁的对象。然后当没有更多的 shared_ptr 拥有该指针的对象时,它将被删除,但它不是用 new 创建的,所以这是一个严重的错误。 (你在另一个函数中做对了,所以我不确定你为什么在 setupMesh 中做错了)。

如果您希望shared_ptr 拥有一个对象,您需要使用new 创建它,或者最好使用std::make_shared 创建它:*

shared_ptr<ofMesh> mesh = std::make_shared<ofMesh>();
mesh0->setMode(OF_PRIMITIVE_LINE_STRIP);
mesh->setupIndicesAuto();
mesh->addVertex(root->location);
mesh->addColor(ofColor(0));

meshes.push_back(shared_mesh);

checkChildren(root, mesh.get());

这会立即创建一个由shared_ptr 拥有的对象,因此转移shared_ptr 不能拥有的东西的所有权没有问题。


* 或者您可以使用“空删除器”,但这对于这个答案来说太高级了,并且无法使用这样的自动变量。

【讨论】:

  • 这太好了,你真的帮助我理清了一些我对此的理解。它不再抛出任何错误。显然我正在创建的树比我想象的要大得多,所以现在我要解决新问题了。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-09
  • 1970-01-01
  • 1970-01-01
  • 2019-07-06
  • 1970-01-01
  • 2013-10-20
相关资源
最近更新 更多