我有一个基类及其子类:
class Base {
public:
virtual void hi() {
cout << "hi" << endl;
}
};
class Derived : public Base {
public:
void hi() override {
cout << "derived hi" << endl;
}
};
尝试创建一个辅助函数来创建派生对象的唯一指针。
1)这个有效:
std::unique_ptr<Base> GetDerived() {
return std::make_unique<Derived>();
}
2)但是,这个编译失败:
std::unique_ptr<Base> GetDerived2() {
auto a = std::make_unique<Derived>();
return a;
}
- std::move 有效:
std::unique_ptr<Base> GetDerived3() {
auto a = std::make_unique<Derived>();
return std::move(a);
}
4)如果我创建一个 Base 实例,两者都可以工作:
std::unique_ptr<Base> GetDerived4() {
auto a = std::make_unique<Base>();
return a;
}
std::unique_ptr<Base> GetDerived5() {
auto a = std::make_unique<Base>();
return std::move(a);
}
为什么(2)失败但其他人工作?
原文由 MaxHeap 发布,翻译遵循 CC BY-SA 4.0 许可协议
std::unique_ptr
不可复制,只能移动。您可以从声明为返回std::unique_ptr<Base>
return std::make_unique<Derived>
函数中获得 --- 的原因是存在从一个到另一个的转换。所以 1) 相当于:
由于从
std::make_unique
返回的值是一个右值,所以返回值是移动构造的。将其与 2) 进行对比,相当于:
由于
a
是一个左值,返回值必须是复制构造的,而std::unique_ptr
是不可复制的。之所以有效,是因为您将左值
a
转换为右值,并且可以移动构造返回值。和 5) 工作,因为你已经有一个
std::unique_ptr<Base>
并且不需要构造一个来返回。