具有继承的模板参数推理



考虑这个小程序:

#include <memory>
#include <vector>
class Holder {
std::vector<std::unique_ptr<A> > _items;
public:
void push(A *v) {
//Perform some checks and other stuff before pushing
_items.emplace_back(v);
};
void push(std::unique_ptr<A> &v) {
push(v.release());
};
};
class A {
};
class B : public A {
};
int main()
{
Holder h;
std::unique_ptr<A> a;
std::unique_ptr<B> b;
// It works but it's too verbose
h.push(a.release());
h.push(b.release());
// It works for a because it has the right type but not for b
h.push(a);
h.push(b);
}

我想知道是否有一种简单的方法可以编写h.push(b)行,而不需要自己拥有所有权。

我不想使用*b,因为指针必须在push方法中失去所有权,并且我希望push方法尽可能易于使用。

我觉得我应该删除push重载,从Holder类中获取unique_ptr,并使用第一个有效的示例。

知道吗?

这是正确的签名:

void push(std::unique_ptr<A> v) {
//Perform some checks and other stuff before pushing
push(std::move(v));
}

取得unique_ptr表示您正在取得所有权。

呼叫现场:

// It works but it's too verbose
h.push(std::move(a));
h.push(std::move(b));

这既是因为它是必需的,也是因为您希望更改所有权的代码是明确的。

注意,std::move(b)代码将导致未定义的行为,因为A缺少虚拟析构函数。

// It works for a because it has the right type but not for b
h.push(a);

这个代码是有毒的,会导致错误。您只是默默地更改了unique_ptr的所有权。auto_ptr具有此属性,并且被发现几乎不可能正确使用,因此被弃用,然后从标准中删除。

不要编写使unique_ptr表现得像auto_ptr的代码。

您应该移动而不是通过引用传递对象:

void push(std::unique_ptr<A> v) {
push(v.release());
};

然后:

h.push(std::move(a));
h.push(std::move(b));

但是唯一指针上的任何release都是臭味,所以用另一种方式实现推送:

void push(A *v) {
//Perform some checks and other stuff before pushing
push(std::unique_ptr<A>(v));
};
void push(std::unique_ptr<A> v) {
_items.push_back(std::move(v));
};

并添加虚拟析构函数。

对于std::unique_ptr,您应该始终拥有所有权,在这种情况下,您不需要担心释放和创建新指针。相反,使用std::move函数,它是为此而设计的。您可以将推送功能更改为:

void push (std::unique_ptr<A> v) { _items.push_back(std::move(v)); }

然后你会用输入指针

h.push(std::move(a));
h.push(std::move(b));

最新更新