指代您不拥有的“ std :: unique_ptr”(使用原始指针?)

tjw*_*992 1 c++ shared-ptr weak-ptr unique-ptr c++11

通常,如果您使用a std::shared_ptr指向对象,并且要创建另一个指向该对象的不共享所有权的指针,则会创建一个std::weak_ptr

// Create a shared pointer to own the object
std::shared_ptr<int> p = std::make_shared<int>(42);

// Create a weak pointer (that does not own the object)
std::weak_ptr<int> q(p);

// Use the weak pointer some time later
if (std::shared_ptr ptr = q.lock()) {
  // use *ptr
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,涉及到该如何处理std::unique_ptr

使用唯一指针可确保当前资源由其std::unique_ptr自身专有。但是,如果我想创建一个指向不拥有该资源的资源的指针,该怎么办?我不能使用a,std::weak_ptr因为弱指针旨在与的引用计数一起使用std::shared_ptr。我会在这里使用原始指针吗?还是有更好的选择?

// Create a unique pointer to own the object
std::unique_ptr<int> p = std::make_unique<int>(42);

// Create a non-owning pointer to the same object
// Is this really the best way?
int* q = p.get();

// Use the pointer some time later
if (q != nullptr) {

  // Imagine this may be multithreaded...
  // what happens if p.reset() is called by another thread while the current thread is RIGHT HERE.

  // use *q
}
Run Code Online (Sandbox Code Playgroud)

我可以想到的创建指向a拥有的对象的非所有者指针的唯一方法std::unique_ptr是使用原始指针,但是从上面的代码可以看出,这可能会导致线程化应用程序出现问题。有没有更好的方法可以实现相同的目标?

Xir*_*ema 7

Based on your last example, this is a scenario where std::shared_ptr and std::weak_ptr should be used.

std::unique_ptr and a non-owning Raw Pointer should be used in the scenario where you have a guarantee that the smart pointer will outlive the raw pointer.

class A {
    std::unique_ptr<int> ptr = std::make_unique<int>(5);
public:
    int* get_ptr() const{return ptr.get();}
};

class B {
    A a;
public:
    void do_something() {
        //int * ptr = a.get_ptr();//Valid, but not advised
        int & ref = *a.get_ptr();//Preferred
        ref++;
    }
};
Run Code Online (Sandbox Code Playgroud)

If you can make this guarantee, you should be using std::unique_ptr and a raw pointer to represent this object. This is ideomatically correct.

If, however, you can't guarantee lifetime at the time you need to manipulate the object, then references should be provided by std::weak_ptr, which are used to acquire ownership (even if only temporarily!) to make changes.

class A {
    std::shared_ptr<int> ptr = std::make_shared<int>(5);
public:
    std::weak_ptr<int> get_ptr() const {
        return ptr;//Implicitly converts
    }
    void destroy() {
        ptr.reset();
    }
};

class B {
    std::weak_ptr<int> ptr;
public:
    B(std::weak_ptr<int> ptr) : ptr(ptr) {}
    void do_something() {
        if(auto owned_ptr = ptr.lock()) {//owned_ptr will be deduced to be of type std::shared_ptr<int>
            *owned_ptr++; //Guaranteed to only execute if the pointer is still valid
        }
    }
};

int main() {
    A a;
    B b(a.get_ptr());
    if(get_random_value() > 10)
        a.destroy();
    b.do_something();
}
Run Code Online (Sandbox Code Playgroud)

  • `//int * ptr = a.get_ptr();//有效,但不推荐 int &amp; ref = *a.get_ptr();//Preferred` 为什么?两种情况都做完全相同的事情。如果指针从您的下方被删除,那么您将留下一个悬空引用,它与悬空指针一样糟糕。 (2认同)

ein*_*ica 6

这取决于额外的指针是否会超过unique_ptr

  • 如果非所属指针绝对不能活得比unique_ptr:使它成为一个普通的指针。谁得到这种指针都可以假定它是有效的,但不能假定拥有它所指向的内存。
  • 如果非所属指针可能活得比unique_ptr:您的原始指针是不是真正的“唯一”; 并且您应将a替换为unique_ptra shared_ptr并传递a weak_ptr作为非所有者副本。

我刚刚注意到,该答案基本上是Xirema答案的简要概述。请投票/接受该答案!