代码之家  ›  专栏  ›  技术社区  ›  OneRaynyDay

在这种情况下,我应该使用智能指针吗?

  •  2
  • OneRaynyDay  · 技术社区  · 8 年前

    我知道进入规则是始终使用 shared_ptr s或其他智能指针。然而,我不知道在没有复制的情况下如何准确地实现它 std::make_shared

    问题

    struct foo{
        std::vector<foo*> v;
    };
    

    这使我可以执行以下操作:

    foo add(foo& f1, foo& f2){
        return foo {&f1, &f2};
    }
    

    这很好,因为这两个节点将成为新节点的子节点。

    我希望正确评估以下内容:

    foo x, y;
    auto z = add(x,y);
    assert(z.v[0] == &x && z.v[1] == &y);
    

    如果这些元素是在堆上分配的,而有人在不知不觉中可能会这样做,那么我们将遇到内存泄漏。因此,最好的方法是为RAII使用智能指针:

    struct foo{
        std::vector<std::shared_ptr<foo> > v;
    };
    
    foo add(foo& f1, foo& f2){
        return foo {std::make_shared<foo>(f1), std::make_shared<foo>(f2)};
    }
    

    这很好,但是 . 假设复制需要很长的时间,我们不想产生这样的成本。

    我们绝对不能:

    foo add(foo& f1, foo& f2){
        return foo {std::shared_ptr<foo>(&f1), std::shared_ptr<foo>(&f2)};
    }
    

    z 在里面 z = x+y delete 在每个 x y 删去

    那么在这种情况下我该怎么办?

    如果我需要提供更多关于上下文的信息,请告诉我。

    1 回复  |  直到 8 年前
        1
  •  3
  •   StoryTeller - Unslander Monica    8 年前

    通过智能指针接受 . 正确应用智能指针的概念意味着您必须考虑数据的所有权语义,而不是自动调用new/delete。

    您接受对非常量对象的引用。这并不意味着共享,只意味着修改对象。正如你正确指出的,仅仅创建指向它们的智能指针就意味着灾难。

    的调用方 add 应该 改变 对此:

    foo add(std::shared_ptr<foo> f1, std::shared_ptr<foo> f2){
        return foo{f1, f2};
    }
    

    现在,用户 可以把这件事搞砸是故意的。但他们很可能不会。此外,现在说用户在调用代码方面有更大的灵活性。它们可以控制它们传递的每个对象的分配器和删除器。