unique_ptr C++03 仿真中的 move 函数
我试图了解 C++03 模拟 unique_ptr 是如何实现的。 unique_ptr 很像 std::auto_ptr 但更安全。在 auto_ptr 隐式(即静默)转移所有权的情况下,它会抛出编译器错误。例如,一个简单的作业。函数 move
是模拟 unique_ptr 安全性的关键。
问题:
- 为什么有三个移动函数?
第三个移动函数接受引用并将其转换为右值,其实现(简化)如下。
T 移动(T &t) { 返回 T(detail_unique_ptr::rv
(t)); }
在上面的代码中,对 T 的显式转换似乎没有必要。事实上,Visual Studio 2010 在没有显式转换为 T 的情况下非常满意。g
T move(T &t) {
return detail_unique_ptr::rv<T>(t);
}
++、clang、Comeau 但不喜欢第二个版本。这些编译器抱怨没有 unique_ptr
的构造函数将 detail_unique_ptr::rv
作为参数。这是为什么? unique_ptr 已经定义了一个(非显式)构造函数,该构造函数采用 detail_unique_ptr::rv
作为参数。为啥那个不自动捡起来?
I'm trying to understand how C++03 emulation of unique_ptr is implemented. unique_ptr is quite like std::auto_ptr but safer. It spits out compiler errors in cases where auto_ptr would have transferred ownership implicitly (i.e., silently). For example, a simple assignment. Function move
is the key behind emulated unique_ptr's safety.
Questions:
- Why are there three move functions?
The third move function that accepts a reference and turns it into an rvalue, is implemented (simplified) as follows.
T move(T &t) { return T(detail_unique_ptr::rv<T>(t)); }
In the above code, an explicit conversion to T seems kind of unnecessary. In fact, Visual Studio 2010 is perfectly happy without an explicit conversion to T.
T move(T &t) {
return detail_unique_ptr::rv<T>(t);
}
g++, clang, Comeau, however, do not like the second version. These compilers complain that there is no constructor for unique_ptr<T>
that takes detail_unique_ptr::rv<T>
as a parameter. Why is that? unique_ptr already defines a (non-explicit) constructor that takes detail_unique_ptr::rv<T>
as a parameter. Why isn't that one picked up automatically?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
原因是因为如果不执行用户定义的转换(通过将右值传递给 unique_ptr 的 rv 构造函数),则无法使用另一个 unique_ptr 初始化 unique_ptr。但是,当未显式调用
unique_ptr
的构造函数(如unique_ptr(...)
中)时,您会执行复制初始化,在您的情况下,首先成功构造一个右值临时 unique_ptr但随后无法将该临时值复制到返回值目标对象中,因为在该副本中不允许用户定义的转换(这也称为原则规则“初始化中不允许有两个用户定义的转换”)。 Msvc 允许副本使用采用非常量 unique_ptr 引用的 ctor,这是非标准的。当从同一类的对象进行类的复制初始化时,不存在这样的两步初始化。源对象只是传递给
unique_ptr
的非显式构造函数,该构造函数将使用 rv 构造函数将其转换为rv
,并通过这种方式成功构造返回价值目标对象。出于同样的原因,不存在从
unique_ptr
到unique_ptr
的隐式转换。在第一步中,将成功创建unique_ptr
,但是当将该临时对象复制到unique_ptr
目标对象时,没有用户定义的限制可以使用转换来阻止成功。The reason is because you cannot initialize a unique_ptr with another unique_ptr without doing a user defined conversion (to rv, by passing the rvalue to the rv-taking constructor of unique_ptr). However when not explicitly calling the ctor of
unique_ptr
(as inunique_ptr(...)
), you do a copy initialization which in your case first successfully constructs a rvalue temporary unique_ptr but then fails to copy that temporary into the return value target object, because in that copy, no user defined conversions are allowed (this is also known as the principle rule "no two user defined conversions in an initialization"). Msvc allows the copy to use the ctor taking a nonconst unique_ptr reference, which is nonstandard.When doing copy initialization of a class from an object of the same class, there is no such two-step initialization. The source object is just passed to the non-explicit constructors of
unique_ptr
, which will convert it torv
using the rv-taking constructor, and by that way successfully construct the return value target object.For the same reason, there is no implicit conversion from
unique_ptr<Derived>
tounique_ptr<Base>
. In the first step, aunique_ptr<Base>
will be successfully created, but then when copying that temporary into theunique_ptr<Base>
target object, the restriction that no user defined conversions can be used prevents success.