Gil*_*ils 6 c++ move move-semantics c++11
我正在阅读 Nicolai M. Josuttis 的《C++ Move Semantics - The Complete Guide》一书(恕我直言,这本书相当不错),我不确定我是否同意其中一个示例中的评论。
引用(来自 6.1.2 - 移出对象的保证状态):
类似的代码可用于释放唯一指针使用的对象的内存:
draw(std::move(up)); // the unique pointer might or might not give up ownership
up.reset(); // ensure we give up ownership and release any resource
Run Code Online (Sandbox Code Playgroud)
让我们假设up变量确实是unique_ptr,并且draw函数接收unique_ptr值(否则,将指针移动到“passed-by-ref”函数有什么意义)。
reset我知道调用“移出”对象是合法的。但我不明白的是为什么它是“必需的”,以便“确保我们放弃所有权并释放任何资源”以及“唯一指针可能会或可能不会”是如何可能的放弃所有权”怎么可能?
毕竟,unique_ptrs 无法复制,而且整个想法是它们仅保证一种所有权。
因此,据我所知,如果我的两个假设是正确的,则无需调用该reset函数来确保所有权被放弃。
我错过了什么吗?
首先,如果参数被值接受,那么我们就可以保证它实际上是被移动的,而不仅仅是可能,并且放弃了资源的所有权(除非移动构造函数不执行任何操作,但这会是无意义的)。.reset()由于两个可能的原因,我们可能不得不另外调用:
.reset()参数并不总是从考虑以下签名:
\nvoid draw(std::unique_ptr<T> &&uptr);\nRun Code Online (Sandbox Code Playgroud)\n这样的签名通常优于通过CppCoreGuidelines F.18 按值接受移出参数:对于 \xe2\x80\x9cwill-move-from\xe2\x80\x9d 参数,通过 X&& 和 std::move 参数传递,尽管像这样的类型有例外std::unique_ptr。
在这种情况下,除非我们查看其实现,否则我们不知道是否会draw从“确定”移动:uptr
void draw(std::unique_ptr<T> &&uptr) {\n // If \'condition\' is false, then \'uptr\' won\'t be moved from, and the\n // caller may have to .reset() to free up resources immediately.\n if (condition) {\n process_further(std::move(uptr));\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n.reset()交换移动分配此外,一些人倾向于按如下方式实现移动赋值运算符:
\nT& operator=(T&& other) noexcept {\n this->swap(other);\n return *this;\n}\n\nvoid draw(std::unique_ptr<T> &&uptr) {\n // This effectively swaps \'something\' with \'uptr\', which means that\n // the caller has to .reset() to free the resources in \'something\',\n // unless they can rely on the destructor of \'uptr\' to do that.\n something = std::move(uptr);\n}\nRun Code Online (Sandbox Code Playgroud)\n这会强制调用者在希望立即释放这些资源时使用.reset(),而不是在参数超出范围时使用。
没有标准库类型实现这样的移动分配,总的来说这不是一个好主意,但它是有效的,并且可能会迫使我们进行调用。
\n