注意:底部有一个有趣的 EDIT
如果您不想对拥有的指针类型进行参数化或重载,则最好采用 ashared_ptr<>
并强制转换unique_ptr<>
. 我能想到的任何非模板解决方案都至少具有与 a 相同的开销shared_ptr
,大多数需要多态调用、自由存储分配或两者兼而有之。
您可能能够shared_ptr
通过采用某种类型的代理转换器来自动转换,这应该允许您采用unique_ptr
R 值或 ashared_ptr
而无需强制转换或显式转换(除了move()
)并提取可用shared_ptr
以存储在您的实例中。这是一个例子:
#include <iostream>
#include <memory>
#include <utility>
using namespace std;
// Take an instance of gimme_owned_ptr<T> to save off a shared_ptr<T>
// from either a shared_ptr or unique_ptr.
template<typename T>
struct gimme_owned_ptr {
// Make the two constructors templates so we can accept
// any convertible owning pointer:
template<typename S>
gimme_owned_ptr( unique_ptr<S> p )
: p_( shared_ptr<S>( move(p) ) )
{ }
template<typename S>
gimme_owned_ptr( shared_ptr<S> p )
: p_( p )
{ }
shared_ptr<T> get() const {
return p_;
}
private:
shared_ptr<T> p_;
};
struct Foo {
void operator()() const { v_call(); }
virtual ~Foo() { }
private:
virtual void v_call() const = 0;
};
struct Bar {
Bar( gimme_owned_ptr<Foo const> const &gop )
: foo_( gop.get() )
{ }
void operator()() const { (*foo_)(); }
private:
shared_ptr<Foo const> foo_;
};
struct Baz : Foo {
private:
virtual void v_call() const { cout << "Baz()()\n"; }
};
int main() {
unique_ptr<Baz> upf( new Baz() );
shared_ptr<Baz> spf( new Baz() );
Bar upb( move( upf ) );
Bar spb( spf );
upb();
spb();
}
是的,此解决方案确实使用模板,但仅用于gimme_owned_ptr
实用程序类模板,并且仅用于重用和转换。您自己的类(Bar
在这种情况下)不需要是模板,也不需要重新实现gimme_owned_ptr
以将其与另一种类型一起使用。
======== 编辑 ========
unique_ptr
我刚刚检查过,从to的内置转换shared_ptr
基本上完成了gimme_owned_ptr
我上面写的所有类。如果该类采用 类型shared_ptr<T>
,则传递 amove(unique_ptr<S>)
将导致可行的转换。因此,您真正需要的只是获取 a shared_ptr
,而用户唯一要做的就是调用move()
s unique_ptr
(无论如何他们都应该这样做)。使用 like 的唯一原因gimme_owned_ptr
是接受不同的指针混合或以不同的方式接受它们。(例如,您可以通过在内部调用move()
a 来避免不必要的事情,但这可能是个坏主意,因为它会默默地夺取所有权。)unique_ptr<S>&
move()