给定 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
,但没有复制构造函数。
此问题是 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
,但没有复制构造函数。