c++ - 我是否总是必须使用 unique_ptr 来表达所有权?

标签 c++ unique-ptr

假设我有一个 A 类,它拥有 B 类的一个对象。

  • A 负责创建和删除 B 的该对象。
  • 所有权不得转让给其他类别。
  • 创建 A 的对象后,B 的对象将永远不会被重新初始化。

通常,据我所知,在现代 C++ 中,我们会使用 unique_ptr 来表示 A 是该对象/引用的所有者:

// variant 1 (unique pointer)
class A {
  public:
    A(int param) : b(std::make_unique<B>(param)) {}

    // give out a raw pointer, so that others can access and change the object 
    // (without transferring ownership)
    B* getB() {
      return b.get();
    }
  private:
    std::unique_ptr<B> b;
};

有人建议我也可以使用这种方法:

// variant 2 (no pointer)
class A {
  public:
    A(int param) : b(B(param)) {}

    // give out a reference, so that others can access and change the object 
    // (without transferring ownership)
    B& getB() {
      return b;
    }
  private:
    B b;
};

据我了解,主要区别在于,在变体 2 中,内存是连贯分配的,而在变体 1 中,B 对象的内存可以分配在任何地方,并且必须首先解析指针才能找到它。 当然,如果 A 的公共(public)接口(interface)的用户可以使用 B*B&,情况也会有所不同。 但在这两种情况下,我确信所有权仍属于 A,因为我需要它。

我是否总是必须使用变体 1 (unique_ptrs) 来表达所有权? 使用变体 2 而不是变体 1 的原因是什么?

最佳答案

所有权可以通过不同的方式表达。

您的B b变体 2 是最简单的所有权形式。类的实例A独占地拥有存储在 b 中的对象并且所有权不能转移给另一个对象或(成员)变量。

std::unique_ptr<B> b表达对 std::unique_ptr<B> 管理的对象的唯一但可转让的所有权.

还有 std::optional<B> , std::vector<B> , … 或 std::variant<B,C> ,表示所有权。

Also of course, it makes a difference if users of A's public interface can work with a B* or a B&. But in both cases, I am sure that ownership stays within A as I need it.

您始终可以创建一个返回 B* 的成员函数。无论成员(member)是否B b ,或std::unique_ptr<B> b (或者也适用于 std::optional<B>std::vector<B> 、… std::variant<B,C> )

有趣的是这段代码:

变体 1

class A {
  public:
    A(int param) : b(B(param)) {}

    // give out a reference, so that others can access and change the object 
    B& getBRef() {
      return b;
    }


    B* getB() {
      return &b;
    }
  private:
    B b;
};

那么问题就少了:

变体 2

class A {
  public:
    A(int param) : b(std::make_unique<B>(param)) {}

    // give out a raw pointer, so that others can access and change the object 
    // (without transferring ownership)
    B* getB() {
      return b.get();
    }
  private:
    std::unique_ptr<B> b;
};

对于变体 2 情况,调用 A 的另一个成员函数可能会使指针无效(例如,如果该函数将另一个对象分配给 unique_ptr )。而对于变体 1,返回的指针(或引用)的有效性由 A 实例的生命周期给出。

无论如何,你都必须处理 B *作为非拥有原始指针,并在文档中明确说明该原始指针的有效时间。


您选择哪种所有权取决于实际用例。 大多数时候,您会尝试保持最简单的所有权B b 。如果该对象是可选的,您将使用 std::optional<B> .

如果实现需要它,例如如果您计划使用 PImpl,如果数据结构可能阻止使用 B b (就像树形或图形结构的情况),或者如果所有权必须可转让,您可能需要使用 std::unique_ptr<B> .

关于c++ - 我是否总是必须使用 unique_ptr 来表达所有权?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69754776/

相关文章:

c++ - 随机 double 总是无限的

c++ - Eclipse CDT : no rule to make target all

c++ - 有没有办法在 VS2012 中编写 make_unique() ?

c++ - unique_ptr 与 move 的不同行为?

c++ - 智能指针是否支持通过指针调用成员函数?

c++ - SSE42 & STTNI - PcmpEstrM 比 PcmpIstrM 慢两倍,这是真的吗?

c++ - 二叉搜索树实现

c++ - 复制构造函数……进退两难

c++ - 原始指针在 vector<T> 中工作,而 unique_prt 不工作

c++ - 多重继承和unique_ptr销毁