引用一个你不拥有的 "std::unique_ptr"(使用原始指针?)

Referring to a "std::unique_ptr" that you don't own (use a raw pointer?)

通常,如果您使用 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
}

我的问题是,当涉及到 std::unique_ptr 时,你是怎么做到的?

使用唯一指针可确保当前资源由 std::unique_ptr 本身独占。但是,如果我想创建一个指向不拥有该资源的同一资源的指针怎么办?我不能使用 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
}

我能想到的创建指向 std::unique_ptr 拥有的对象的非拥有指针的唯一方法是使用原始指针,但正如您从上面的代码中看到的那样,这可能会导致问题在线程应用程序中。有没有更好的方法来实现同样的目标?

根据您上一个示例,在这种情况下应使用 std::shared_ptrstd::weak_ptr

std::unique_ptr 在保证智能指针的寿命比原始指针长的情况下,应使用非拥有原始指针。

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++;
    }
};

如果你能保证,你应该使用 std::unique_ptr 和一个原始指针来表示这个对象。这在思想上是正确的。

但是,如果您不能保证在需要操作对象时的生命周期,那么 std::weak_ptr 应该提供引用,用于获取所有权(即使只是暂时的!)进行更改。

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();
}

这取决于额外的指针是否可以比 unique_ptr

  • 如果非拥有指针绝对不能超过unique_ptr:使它成为普通指针。得到这种指针的人可以认为它是有效的,但不能假定拥有它指向的内存。
  • 如果非拥有指针 可能比 unique_ptr 长寿:您的原始指针并不是真正的 "unique";并且您应该将 unique_ptr 替换为 shared_ptr 并传递 weak_ptr 作为非拥有副本。

刚刚注意到这个回答基本上是对的简单总结。请upvote/accept回答!