c++ - 返回 unique_ptr 变量会返回错误
问题描述
我遇到了一个奇怪的问题。以这种方式编写时,我在 setGetDog() 方法中收到错误消息:
class Dog
{
public:
void bark() { std::cout << "Bark!" << std::endl; }
};
class test
{
public:
std::unique_ptr<Dog> setGetDog()
{
if (!dog_)
{
dog_ = std::make_unique<Dog>();
}
return dog_;
}
private:
std::unique_ptr<Dog> dog_;
};
int main()
{
auto testClass = std::make_unique<test>();
auto dog = testClass->setGetDog();
}
错误是这样的:
error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Dog; _Dp = std::default_delete<Dog>]'
但是当我将实现更改为:
std::unique_ptr<Dog> setGetDog()
{
return std::make_unique<Dog>();
}
它工作得很好。
怎么回事dog_
?我不明白为什么错误指出它在test
调用该方法时实际上仍然存在时被删除(等等dog_
)。
我知道我可以用其他方式写这个,但我特别好奇为什么这个实现上的行为是这样的。
任何人都可以请赐教吗?
解决方案
对象具有几种不同类型的值类别/情况,它们会影响从函数返回的方式。让我们先看看右值类别。当你这样做
std::unique_ptr<Dog> setGetDog()
{
return std::make_unique<Dog>();
}
std::make_unique<Dog>()
按值返回,使返回对象成为右值。这意味着当编译器返回对象时,它将隐式移动它。(编译器也可以省略副本,但这对于本次讨论无关紧要)由于对象已移动,因此您没有任何问题,因为std::unique_ptr
它是可移动的。
第二种情况是当你有一个左值,但它是一个函数本地对象。如果你有
std::unique_ptr<Dog> setGetDog()
{
auto ptr = std::make_unique<Dog>();
return ptr;
}
这ptr
是一个左值,但它正在消失,所以我们可以称它为 xvalue(到期值)。对于 xvalues,当您返回它们时,编译器会尝试移动它,因为在这种情况下移动它是一种安全的操作。如果移动操作不存在/不可行,则编译器回退到复制。由于std::unique_ptr
是可移动的,因此它可以毫无错误地移动。
最后一种情况是当你有一个像你一样的普通左值时
class test
{
public:
std::unique_ptr<Dog> setGetDog()
{
if (!dog_)
{
dog_ = std::make_unique<Dog>();
}
return dog_;
}
private:
std::unique_ptr<Dog> dog_;
};
这里,dog_
是类的成员,而不是函数本地的对象。这意味着编译器唯一能做的就是尝试复制。由于您无法复制 a unique_ptr
,因此您会收到错误消息。你需要return std::move(dog_);
编译它,但如果你dog_
在课堂上这样做,那将是空的。
推荐阅读
- javascript - 是否有适用于类组件的 React Material-UI makeStyles() 函数的非挂钩替代方案
- html - 为什么不显示:阻止元素集空间像其他元素一样被保留?
- java - 如何让bazel在java中通过maven_jar递归下载依赖项
- excel-formula - 我需要在公式输出范围内自动计算 UNIQUE 值,该范围可能为空白,也可能不为空白
- r - 如何在数据帧列表(或子集数据帧)上循环地理映射函数
- node.js - 使用 node.js 从 2 个 postgres 表中查询所有数据
- javascript - Javascript如何访问用jQuery加载的HTML文件中的元素
- xamarin - Xamarin.UITest 中的 Environment.System.Environment.SpecialFolder.MyDocuments 与应用程序中的不同
- json - 在 ASP.NET 中工作的 JSON 查询在 ASP.NET-Core 3.0 中无法将字段查询从数据库重新调整到用户表单
- tensorflow - Tensorflow:找出预构建的 tensorflow 轮子所针对的 CUDA/CuDNN 版本