给定 returns a unique_ptr 的函数,如何使 class 成为指针的(部分)所有者

How can a class be made (partial) owner of a pointer given a function that returns a unique_ptr

此问题是 Why doesn't returning a std::unique_ptr violate unique_ptr's deleted copy constructor? (which is answered here: Returning unique_ptr from functions )

的后续问题

这让我回到了最初遇到的问题。

我必须使用 returns 一个 std::unique_ptr 的函数(在我的控制范围之外)。我希望 class 的实例具有对 unique_ptr 封装的对象的引用,但我不清楚并且摸索着实现它所需的语法。

我希望这个示例代码让我的意图清楚,因为我找不到正确的model/syntax来进行这个编译:我想要实例class PtrOwner 能够“拥有”对由函数 getUniquePtr():

返回的 unique_ptr 封装的底层对象的某种形式的引用
// main.cpp
#include <memory>
#include <iostream>

std::unique_ptr<int> getUniquePtr() {
  return std::unique_ptr<int>(new int( 42 ));
}

class PtrOwner {
  std::unique_ptr<int> p_;

public:
  PtrOwner( std::unique_ptr<int> p ) : p_(p) {}
};

int main( int argc, char* argv[] ) {
  PtrOwner po( getUniquePtr() );

  return 0;
}
$ g++ --version && g++ -g ./main.cpp && ./a.out
g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

./main.cpp: In constructor ‘PtrOwner::PtrOwner(std::unique_ptr<int>)’:
./main.cpp:13:44: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’
   PtrOwner( std::unique_ptr<int> p ) : p_(p) {}
                                            ^
In file included from /usr/include/c++/6/memory:81:0,
                 from ./main.cpp:2:
/usr/include/c++/6/bits/unique_ptr.h:359:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^~~~~~~~~~

什么是好的 practice/accepted 惯例来实现这一目标? 我尝试摸索 PtrOwner 拥有 shared_ptr 的概念,但我也不擅长 class,并且无法实现所需的语法:

// main.cpp
#include <memory>
#include <iostream>

std::unique_ptr<int> getUniquePtr() {
  return std::unique_ptr<int>(new int( 42 ));
}

class PtrOwner {
  std::shared_ptr<int> p_;

public:
  PtrOwner( const std::unique_ptr<int>& p ) : p_(p) {}
};

int main( int argc, char* argv[] ) {
  PtrOwner po( getUniquePtr() );

  return 0;
}

(我认为第二个代码块的错误对我来说太垃圾了,无法合理地 post 在这里)

您上面示例中的构造函数尝试 复制 unique_ptr,但 unique_ptr 不可复制。

您需要移动它:

#include <utility>

//...

PtrOwner(std::unique_ptr<int>&& p) : p_(std::move(p)) {}

虽然没有部分关于所有权。 PtrOwner 现在是所有者。期间.

要获取对基础对象的引用,请使用 std::unique_ptr::operator*:

int& r = *p_;

r 在这里是对底层对象的引用,可用于为对象分配新值(例如 r = 10;)但不拥有它。该对象将在 r 超出范围时继续存在,并在 PtrOwner 实例超出范围时被销毁(或者,如果所有权已转移,则当前拥有的实体超出范围时).

What is good practice/accepted convention to pull this off?

采纳@TedLyngmo 的建议。这是很好的做法。我将提供一些额外的一般直觉:

如果您的 class 持有 std::unique_ptr 而不是指针 - 您基本上可以忘记其中使用术语“指针”。将其视为不透明的不可复制对象;您绝对不必担心任何堆存储。它有点像 std::vector,但没有复制构造函数。