【发布时间】:2021-10-16 13:04:20
【问题描述】:
给定以下代码:
#include <iostream>
#include <memory>
struct A {};
struct B : public A {};
std::pair<bool, std::unique_ptr<B>> GetBoolAndB() {
return { true, std::make_unique<B>() };
}
std::unique_ptr<A> GetA1() {
auto[a, b] = GetBoolAndB();
return b;
}
std::unique_ptr<A> GetA2() {
auto [a, b] = GetBoolAndB();
return std::move(b);
}
GetA1 无法编译,出现此错误:
C2440: 'return': cannot convert from 'std::unique_ptr<B,std::default_delete<_Ty>>' to 'std::unique_ptr<A,std::default_delete<_Ty>>'
而GetA2 编译时没有错误。
我不明白为什么我需要调用std::move 才能使该功能正常工作。
编辑
澄清一下,正如 DanielLangr 在 cmets 中指出的那样,我的疑问在于
std::unique_ptr<A> GetA3() {
std::unique_ptr<B> b2;
return b2;
}
无需std::move即可编译和转移所有权。
现在我了解到,在 GetA1 和 GetA2 的情况下,如果使用结构化绑定,b 恰好是某个对象的一部分,因此必须将其移动为右值参考。
【问题讨论】:
-
我添加另一个观察:如果在
GetA1中添加std::unique_ptr<B> b2;和return b2;而不是return b;,则代码编译。所以问题似乎与结构化绑定有关。另一方面,static_assert(std::is_same_v<decltype(b), decltype(b2)>);通过了,所以我真的不知道返回b或另一个相同类型的 lobcal 对象有什么区别。 -
您是在问为什么
std::unique_ptr需要被移动一般,即为什么它不可复制,或者您是在问为什么它需要被移动这种具体情况? -
这样想,唯一的指针表示唯一的所有权。这样的所有者只能有一个。如果你返回一个 unique_ptr,那么你基本上是在说:调用 GetA2 的代码将成为唯一指针的新所有者,你必须移动所有权,因此移动
-
@PepijnKramer 我认为您不理解 OP 要求的问题。如果你写
std::unique_ptr<B> b2; return b2;,它将编译和转移所有权,而不需要std::move。我相信 OP 在问为什么它与结构化绑定的工作方式不同。 -
@DanielLangr 哎呀,谢谢。我误读了这个问题。
标签: c++ c++17 unique-ptr move-semantics structured-bindings