在*现代* C++ 中我应该如何管理*无主*指针?

问题描述 投票:0回答:4

modern C++ 中,我应该如何管理 unowned 指针? 我在想类似

weak_ptr
代表
unique_ptr
,但这似乎不存在。

示例

例如,如果我有一个类

A
拥有一个指针,我应该使用
unique_ptr<X>
而不是旧的
X*
指针,例如

class A
{
    std::unique_ptr<X> _myX;
};

但是如果我有另一个类

B
使用这个指针,我在这里该怎么办?使用 C 风格指针我会这样做:

class B
{
    X* _someX;
};

这似乎是正确的,但从代码中并不明显看出我引用了另一个对象的指针(例如读者可能认为我可以不使用智能指针)。

我考虑过以下几点

  • std::shared_ptr<X>
    - 似乎浪费了引用计数,因为
    A
    保证比
    B
    更长寿。
  • std::weak_ptr<X>
    - 仅适用于
    shared_ptr
  • X&
    - 仅当 X& 在 B 的构造函数中可用时才有效

这似乎是一个明显的问题,如果之前有人问过这个问题,我们深表歉意。我环顾四周,看到了 this 问题,但不幸的是,OP 在一种特定情况下询问“可以使用 X* 吗”。我正在寻找我通常应该做什么而不是X*,(如果有的话!)。

c++ smart-pointers
4个回答
10
投票
Bjarne Stroustrup

对此事进行了权衡

指针非常擅长指向“事物”,而

T* 是一个非常好的表示法……指针不擅长的是代表所有权

他提出两个建议:

    考虑
  • T*
     在现代 C++ 中表示“指向 
    T
     的非拥有指针”
  • 如果您希望变量声明
  • 明确记录
    这种非所有权,请使用
    template<typename T> using observer_ptr = T*;

3
投票
这似乎是正确的,但从代码中并不明显看出我引用了另一个对象的指针

理想情况下,它

应该是显而易见的。如果指针拥有资源,那么它应该是一个智能指针。由于它不是智能指针,这意味着它不应该拥有该资源。

也就是说,在现实中,C /古老的C ++ /设计糟糕的接口使用拥有指针,你可以像这样澄清缺乏所有权:

class B { X* _someX; // no ownership };


也可以为此目的定义一个自定义类模板包装器,并且已经有一个

提案将此类模板包含在标准库中,该提案已被采纳为技术规范,但尚未被采纳为标准本身。据我了解,对于这种包装器是否有用还没有达成共识。


1
投票
您的问题很大程度上是基于意见,但我们可以看看核心指南对此的说法:

R.3:原始指针(T*)是非拥有的

原因

(在 C++ 标准或大多数代码中)没有什么可说的,并且大多数原始指针都是非拥有的。我们希望识别出拥有指针,以便我们能够可靠且高效地删除拥有指针所指向的对象。

该指南提倡在原始指针是拥有指针时永远不要使用它。一旦你这样做了,原始指针也很容易表明它是非拥有的。这种解释的缺点是:

异常

主要的一类例外是遗留代码,尤其是必须保持可编译为 C 或通过 ABI 与 C 和 C 风格的 C++ 接口的代码。事实上,有数十亿行代码违反了禁止拥有 T* 的规则,这一事实不容忽视。 [...]

并非所有原始指针都是非拥有的,并且通常我们对此无能为力。但是,如果您的代码是在 C++11 之后编写的,那么使用原始指针应该足以表明它不是拥有指针。


1
投票

https://abseil.io/tips/116 这里对选项进行了很好的讨论。如果您在构建时就有了该东西,并且永远不需要重新指向它,那么 T&

 可能会很好。如果你不这样做,那么“嘿,这可能是 null”是该指针现实的一部分,并且 
T*
 很好 - 现代 C++ 中的“原始”指针通常传达一个可选的、非拥有的引用。

© www.soinside.com 2019 - 2024. All rights reserved.