我正在更新一些auto_ptr用来unique_ptr代替的旧代码。它主要是一个搜索和替换工作,但是我发现我在代码返回a的一个地方遇到了编译错误unique_ptr。
这是说明问题的示例:
#include <string>
#include <iostream>
#include <memory>
#include <utility>
using namespace std;
struct Foo {
unique_ptr<string> us;
Foo() {
this->us = unique_ptr<string>(new string("hello"));
}
unique_ptr<string> bar() {
return this->us;
}
};
int main(int argc, const char **argv) {
Foo foo;
unique_ptr<string> s = foo.bar();
cout << *s << endl;
}
Run Code Online (Sandbox Code Playgroud)
当我编译它时,我得到了:
t1.cpp: In member function ‘std::unique_ptr<std::basic_string<char> > Foo::bar()’:
t1.cpp:17:16: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = std::basic_string<char>; _Dp = std::default_delete<std::basic_string<char> >]’
return this->us;
^~
In file included from /opt/rh/devtoolset-7/root/usr/include/c++/7/memory:80:0,
from t1.cpp:4:
/opt/rh/devtoolset-7/root/usr/include/c++/7/bits/unique_ptr.h:388:7: note: declared here
unique_ptr(const unique_ptr&) = delete;
^~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
如果我更改错误行以指定这样的移动:
return move(this->us);
Run Code Online (Sandbox Code Playgroud)
然后就可以了。
我发现有许多参考资料表明不需要采取任何举动-例如,这个SO问题,以及来自铬项目的这些准则。
我的问题是:在这种情况下,为什么需要明确指定举动?我以某种方式返回实例变量的值是否与事实有关?
如果这是骗人的话,请提前道歉-我敢肯定会问过这个问题,但是我很难找到能找到它的搜索词。
这都是关于语义的。A unique_ptr是唯一的所有权,因此将返回或在中us,但不能同时返回。该标准的规则幸运地保护您免受这种误解。
您可以做的是返回一个临时文件unique_ptr(将被移动):
unique_ptr<string> bar() {
return make_unique<string>("hello, world");
}
Run Code Online (Sandbox Code Playgroud)
但是,如果您需要unique_ptr在多个地方复制一份,根据您的情况似乎如此main(),那么您并不是在寻找唯一的而是共享的所有权。因此,您应该转到shared_ptr:
struct Foo {
shared_ptr<string> us;
Foo() {
us = make_shared<string>("hello, world");
}
shared_ptr<string> bar() {
return us;
}
};
int main(int argc, const char **argv) {
Foo foo;
auto s = foo.bar();
cout << *s << endl;
}
Run Code Online (Sandbox Code Playgroud)
您找到的所有引用都提到返回的对象必须是函数局部变量。您返回一个成员。返回时,成员变量不会被隐式视为右值。
这不是没有道理的。除非明确声明,一个类通常不想失去其资源的所有权。
当函数返回时,无论如何局部函数都会死掉,因此让编译器隐式地蚕食它是一个值得优化的优化。
| 归档时间: |
|
| 查看次数: |
149 次 |
| 最近记录: |