简体   繁体   English

正确使用std :: unique_ptr和std :: weak_ptr

[英]Correct use of std::unique_ptr and std::weak_ptr

How do I correctly use std::unique_ptr and std::weak_ptr in this case? 在这种情况下,如何正确使用std::unique_ptrstd::weak_ptr

struct B;
struct A
{
    B* b;
    float f;

    A(float f, B* parent)
        : f(f), b(parent)
    {}
};

struct B
{
    A a;

    B(float f)
        : a(f, this)
    {}
};

I want to create a B with auto anB = std::unique_ptr<B>(new B(3.0f)) . 我想用auto anB = std::unique_ptr<B>(new B(3.0f))创建一个B My guess would be that A should have a std::weak_ptr<B> b instead of the raw pointer, but to create the std::weak_ptr I need a std::shared_ptr of B ... 我的猜测是A应该具有std::weak_ptr<B> b而不是原始指针,但是要创建std::weak_ptr我需要Bstd::shared_ptr ...
Should A just keep its raw pointer in this case? 在这种情况下, A应该只保留其原始指针吗?

The information provided is not enough information to solve the lifetime management problem. 提供的信息不足以解决寿命管理问题。

You have provided some structure layouts. 您已经提供了一些结构布局。 You have not described how the data in the structures is going to be used, nor anything much about their lifetimes. 您尚未描述结构中的数据将如何使用,也没有描述其寿命。

Structure layouts does not determine lifetime , except a sane structure layout is going to be a function of the data lifetime problem. 结构布局不能确定生存期 ,除非合理的结构布局将取决于数据生存期问题。

What you have done is said "I have some red paint I want to paint a room with. What house should I buy?" 你说的是:“我有一些红色的油漆,我想用它来油漆房间。我应该买什么房子?” Structure layout is useful to solve lifetime issues, and paint is useful to paint rooms in houses, but providing a structure layout does not tell you what smart pointers to use, and the color of house paint doesn't tell you what house to buy. 结构布局对于解决生命周期问题很有用,而油漆对于在房屋中油漆房间很有用,但是提供结构布局不会告诉您使用什么智能指针,房屋油漆的颜色也不会告诉您要买什么房子。

You need to think about what the lifetime of the various objects will be, and try to make that as simple as possible, and then use the smart pointers that make that management easy. 您需要考虑各种对象的寿命,并尝试使其尽可能简单, 然后使用使该管理变得容易的智能指针。

As A doesn't have ownership of B , a raw (non owning) pointer is ok. 由于A没有对B所有权,因此可以使用原始(无所有权)指针。 (but its lifetime should be longer than A ). (但其寿命应比A更长)。

So currently, you have problem with default copy constructor/assignment of B/A which may make A points to old B . 因此,当前,您对B / A的默认副本构造函数/赋值有问题,这可能会使A指向旧B

For the weak_ptr , indeed, B should go in a shared_ptr instead of unique_ptr , and to allow same signature, it should inherit from std::enable_share_from_this ... 实际上,对于weak_ptrB应该进入shared_ptr而不是unique_ptr ,并且为了允许相同的签名,它应该继承自std::enable_share_from_this ...

From our conversation in the comments it seems to me that separating concerns might be in order. 从我们在评论中的谈话,在我看来,分离关注点可能是有序的。

An A is an attribute of a B. There needs to be a canonical store of Bs (that controls lifetime) and there needs to be an index (non-owning) of Bs ordered by some attribute of the B (in this case, one of the As). A是B的一个属性。必须有B的规范存储(控制生存期),并且B的索引(无所有权)需要按B的某些属性排序(在这种情况下,一个B的)。

This argues for two vectors (or some other appropriate container), one containing Bs and the other containing sorted references to Bs. 这主张两个向量(或其他适当的容器),一个包含B,另一个包含对B的排序引用。

You can of course wrap the container and index into another object to provide encapsulation (I have not done this in the trivial example below): 您当然可以将容器和索引包装到另一个对象中以提供封装(在下面的简单示例中我没有做到这一点):

#include <vector>
#include <algorithm>
#include <memory>
#include <functional>

// define the attribute
struct A
{
    float f;

    A(float f)
        : f(f)
    {}
};

// define the object    
struct B
{
    A a1;
    A a2;

    // no back-pointers
    B(float f, float f2)
        : a1(f)
          , a2(f2)
    {}
};


int main()
{
  using b_vec_type = std::vector<B>;

  // build the canonical store      
  b_vec_type bs = { B { 1, 2}, B { 5, 4 }, B { 3, 4 } };

  using a1_index_type = std::vector<std::reference_wrapper<B>>;

  // build the index
  a1_index_type index(bs.begin(), bs.end());

  // sort the index by the attribute we want      
  std::sort(index.begin(), index.end(), 
            [](const B& l, const B& r) {
              return l.a1.f < r.a1.f;
            });

  // now use the index:

  for (const auto& e : index)
  {
    // do something with the Bs, ordered by B::a1
    // e will be of type std::reference_wrapper<B>, which has
    // a conversion operator to B& already defined.
  }


  return 0;
}

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

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