使用observer_ptr

Cof*_*ode 42 c++ smart-pointers c++17

std::observer_ptr库基础技术规范V2 中的构造究竟有什么意义?

在我看来,它所做的一切都是裸露的T*,如果不增加动态内存安全性,这似乎是一个多余的步骤.

在我的所有代码中,我使用std::unique_ptr了我需要明确拥有对象的位置以及std::shared_ptr可以共享对象所有权的位置.

这非常有效并且可以防止意外解除引用已经被破坏的对象.

std::observer_ptr 当然,不保证观察到的物体的寿命.

如果它是从a构造的,std::unique_ptr或者std::shared_ptr我会看到在这样的结构中使用,但任何简单使用的代码T*可能只是继续这样做,如果他们计划移动到任何它将是std::shared_ptr和/或std::unique_ptr(取决于在使用上).


给出一个简单的示例函数:

template<typename T>
auto func(std::observer_ptr<T> ptr){}
Run Code Online (Sandbox Code Playgroud)

如果停止智能指针在观察它们时销毁它们存储的对象将会有用.

但如果我想观察std::shared_ptrstd::unique_ptr我必须写:

auto main() -> int{
    auto uptr = std::make_unique<int>(5);
    auto sptr = std::make_shared<int>(6);
    func(uptr.get());
    func(sptr.get());
}
Run Code Online (Sandbox Code Playgroud)

这使得它不比以下更安全:

template<typename T>
auto func(T *ptr){}
Run Code Online (Sandbox Code Playgroud)

那么,这个新结构的用途是什么?

它只是用于自我记录的来源吗?

Bar*_*rry 34

提案非常清楚地表明它只是用于自我记录:

本文提出observer_ptr了一种(不是非常)智能指针类型,它对其所有者,即对于它所观察到的对象不承担任何责任.因此,它旨在作为原始指针类型的近似替代品,其优点在于,作为词汇类型,它表示其预期用途,而无需代码阅读器的详细分析.

  • 考虑到第一个版本考虑了来自其他智能ptrs的隐式转换......是否有丢弃的记录? (3认同)
  • 与`std :: reference_wrapper`有什么有意义的区别,除了`reference_wrapper`不能为空? (3认同)

Gal*_*lik 30

当您需要共享访问但不需要共享所有权时.

问题是原始指针仍然非常有用,并且具有完全可敬的用例场景.

原始指针由管理智能指针其清理保证,因此,该的寿命内智能指针,它是有道理通过访问实际数据原始指针智能指针是管理.

因此,当我们创建函数时,通常需要一个原始指针,一种承诺函数不会删除该指针的好方法是使用强类型类std::observer_ptr.

将托管的原始指针作为参数传递给std::observer_ptr函数参数时,我们知道该函数不会使用delete它.

这是一个函数说"给我你的指针,我不会干涉它的分配,我会用它来观察"的方式.

顺便说一句,我并不热衷于这个名字,std::observer_ptr因为这意味着你可以看,但不能触摸.但事实并非如此.我会更喜欢的东西access_ptr.

附加说明:

这是一个不同的用例std::shared_ptr.该std::shared_ptr是分享所有权,它应该被用来当你无法确定哪些所属对象将走出去的范围第一次.

std::observer_ptr,而另一方面,是当你想共享的访问,但没有所有权.

std::shared_ptr简单地使用共享访问权限并不合适,因为这可能效率很低.

因此,无论您是使用a 还是管理目标指针,仍然存在原始指针的用例,因此对于a来说是合理的.std::unique_ptrstd::shared_ptrstd::observer_ptr

  • `std:reference_wrapper` 不适合共享访问吗? (2认同)
  • 与reference_wrapper的主要区别在于它可以是nullptr (2认同)

Meh*_*dad 20

它仅用于源自我文档吗?

是.

  • 它不是。如果是这样,“template&lt;typename T&gt; usingobserver_ptr = T*;”就可以达到目的,但事实并非如此。 (2认同)

Jos*_*son 16

提案中可以看出std::observer_ptr,主要是为了记录指针是对象的非拥有引用,而不是拥有引用,数组,字符串迭代器.

但是,使用observer_ptr<T>over 还有其他一些好处T*:

  1. 默认构造observer_ptr将始终初始化为nullptr; 常规指针可以初始化,也可以不初始化,具体取决于上下文.
  2. observer_ptr仅支持对参考有意义的操作; 这强制正确使用:
    • operator[]没有实现observer_ptr,因为这是一个数组操作.
    • observer_ptr因为这些是迭代器操作,所以不能使用指针运算.
  3. 两个observer_ptrs 在所有实现上都有严格的弱排序,这对于两个任意指针都不能保证.这是因为operator<std::less为了observer_ptr(和std::unique_ptrstd::shared_ptr)一样实现的.
  4. observer_ptr<void>似乎没有支持,这可能会鼓励使用更安全的解决方案(例如std::anystd::variant)


Ric*_*est 5

使用std::observer_ptr原始指针的一个好结果是,它提供了一个更好的替代方法,可以替代从C继承的令人困惑且容易出错的多指针实例化语法.

std::observer_ptr<int> a, b, c;
Run Code Online (Sandbox Code Playgroud)

是一个改进

int *a, *b, *c;
Run Code Online (Sandbox Code Playgroud)

从C++的角度来看这有点奇怪,很容易被误输

int* a, b, c;
Run Code Online (Sandbox Code Playgroud)

  • @Mehrdad:`std :: add_pointer_t <T>`似乎更合适(并且它不长于`observer_ptr`). (3认同)