C++0x unique_ptr 取代了scoped_ptr 取得所有权?
我曾经写过这样的代码:
class P {};
class Q: public P {};
class A {
// takes ownership
A(P* p): p_(p) {}
scoped_ptr<P> p_;
};
A a(new Q);
使用C++0x,我应该将A类重写为:
class A {
// takes ownership
A(unique_ptr<P>&& p): p_(p) {}
unique_ptr<P> p_;
};
I used to write code like this:
class P {};
class Q: public P {};
class A {
// takes ownership
A(P* p): p_(p) {}
scoped_ptr<P> p_;
};
A a(new Q);
With C++0x, should I rewrite class A as:
class A {
// takes ownership
A(unique_ptr<P>&& p): p_(p) {}
unique_ptr<P> p_;
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我已经对 comonad 的答案投了赞成票,但有一个警告:
我还没有遇到过 const std::unique_ptr 不如 boost::scoped_ptr 的任何用例。不过,我对这个主题的教育持开放态度。
编辑:
这是
boost::scoped_ptr
的一个用例,我认为应该失败,但没有。std::unique_ptr
确实会失败:如果
boost::scoped_ptr
的承诺是其资源不会逃逸当前作用域,那么它就不太擅长保存该承诺作为 const std::unique_ptr 。如果我们想比较 const boost::scoped_ptr 和 const::std::unique_ptr,我必须问:出于什么目的?它们对我来说似乎是一样的,除了 const std::unique_ptr 允许自定义构造和销毁。I've upvoted comonad's answer, but with a caveat:
I have not come across any use cases where a
const std::unique_ptr
is inferior to aboost::scoped_ptr
. However I'm open to education on the subject.Edit:
Here is a use case of
boost::scoped_ptr
that I think should fail, but does not. It does fail forstd::unique_ptr
:If the promise of
boost::scoped_ptr
is that its resource will not escape the current scope, then it is not as good at holding that promise as aconst std::unique_ptr
. If we want to compare const boost::scoped_ptr to const::std::unique_ptr, I have to ask: for what purpose? They seem the same to me, except that a const std::unique_ptr allows customized construction and destruction.scoped_ptr 是一个 auto_ptr 无复制和无移动语义。
auto_ptrs 总是一个糟糕的选择——这是显而易见的。
每当您想要明确拥有移动语义时,请使用unique_ptr。
每当您想要明确禁止移动语义时,请使用scoped_ptr。
所有指针都允许交换语义,例如
p.swap(q)
。要禁止这些,请使用任何const …_ptr。在某些情况下,您想要使用指向多个可互换对象之一的 scoped_ptr:由于缺乏移动语义,因此非常安全(相对于明显的错误),它不会意外由于意外移动而指向 null。值得一提的是:scoped_ptr仍然可以有效交换。为了使其可移动和/或可复制 - 但仍然具有这些交换语义 - 您可能需要考虑使用指向可交换的 scoped_ptr 的 shared_ptr (通过scoped_ptr: :交换)对象。
有关更多详细信息,请参阅 stackoverflow:smart-pointers-boost-explained。
A scoped_ptr is a auto_ptr without copy and without move semantics.
auto_ptrs are allways a bad choice – that is obvious.
Whenever you want to explicitely have move semantics, use a unique_ptr.
Whenever you want to explicitely disallow move semantics, use a scoped_ptr.
All pointers allow swap semantics, like
p.swap(q)
. To disallow those, use any const …_ptr.There are situations, where you want to use a scoped_ptr pointing to one of several interchangeable objects: Because of the absence of move semantics, it is quite safe (in respect to obvious bugs) that it will not accidentally point to null because of an unintended move. Worth to mention: scoped_ptrs can still be swapped efficiently. To make it movable and/or copyable – but still with these swap semantics – you might want to consider using a shared_ptr pointing to a scoped_ptr pointing to an exchangeable (via scoped_ptr::swap) object.
See stackoverflow:smart-pointers-boost-explained for further details.
IMO 最好使用
unique_ptr
因为它提供了一个附加功能:移动语义。即,您可以为您的类编写移动构造函数等,这与scoped_ptr
不同。此外,unique_ptr
不像scoped_ptr
那样有与之相关的开销,因此它是一个优越的设施。当然,重写的决定取决于您,如果您不需要移动语义,那么重写就没有意义。不要忘记unique_ptr
来自标准库,因此它必须与 C++0x 的任何兼容实现一起提供(当然当它成为现实时:)!IMO it is better to use
unique_ptr
as it provides an additional feature: move semantics. i.e. you can write a move constructor, etc for your class, unlikescoped_ptr
. Also,unique_ptr
doesn't have an overhead associated with it as it is the case withscoped_ptr
, so it is a superior facility. A decision of a rewrite is up to you of course, in case you don't need move semantics then there is no point of the rewrite. Don't forget thatunique_ptr
is from the standard library, so it must be provided with any compliant implementation of C++0x(when it becomes reality of course :)!我不同意 AraK 的观点,认为其中一个更优越。两者之间不存在更好的选择,因为它通常取决于使用情况。这就像说 SmartCar 在所有用途上都优于皮卡车,因为它更轻、更快。事实上,有时您需要卡车,有时则不需要。您应该根据您的需要选择指针。
scoped_ptr 的好处是它增加了一定程度的安全性。通过使用scoped_ptr,您可以声明创建的内存仅适用于该范围,而不再存在,因此您可以获得编译时保护,防止尝试移动它或传输它。
因此,如果您想创建某些东西但限制其范围,请使用scoped_ptr。如果您想创建某些东西并拥有可移动的所有权,请使用 unique_ptr。如果您想创建一些东西并共享该指针并在所有引用都消失时进行清理,请使用shared_ptr。
I have to disagree with AraK on one being superior. There is no such thing as a superior choice between the two as it often depends on usage. That's like saying a SmartCar is superior to a pick-up truck for all uses because it's lighter and faster. In reality, sometimes you need a truck and sometimes you don't. Your choice of pointer should be based on what you need.
The nice thing about scoped_ptr is it adds a level of safety. By using scoped_ptr you are delcaring that the memory created will exist only for that scope and no more, thus you get compile-time protection against attempting to move it or transfer it.
So, if you want to create somethign but limit it's scope, used scoped_ptr. If you want to create something and have ownership be movable, use unique_ptr. If you want to create something and share that pointer and cleanup when all referencers are gone, use shared_ptr.
编辑:我的错,您确实需要在初始化程序中编写
move(p)
。std::move
将给定的任何内容视为右值引用,在您的情况下,即使您的参数是对某些内容的右值引用,也会将其传递给其他内容(例如p_
的构造函数)将传递左值引用,默认情况下绝不传递右值引用。根据卡鲁的评论,还添加了必要的包含以使我的代码可编译。
例如:
另外,在您原来的示例中,您应该像这样重写类 A:
class A {
// 取得所有权
A(unique_ptr
&& p): p_(std::move(p)) {}
};
Edit: my bad, you DO need to write
move(p)
inside the initialiser.std::move
treats whatever it's given as an rvalue reference, and in your case, even though your argument is an rvalue reference to something, passing it to something else (likep_
's constructor) will pass an lvalue reference, never an rvalue reference by default.Per Karu's comment, also added necessary includes to made my code compilable.
For example:
Also, in your original example, you should rewrite class A like this:
class A {
// takes ownership
A(unique_ptr
&& p): p_(std::move(p)) {}
};