I was updating some old code that uses auto_ptr
to use unique_ptr
instead. It was mostly a search and replace job, but I found I was getting a compilation error in one place where the code returns a unique_ptr
.
Here is an example that illustrates the issue:
#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;
}
When I compile that, I get this:
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;
^~~~~~~~~~
If I alter the line with the error to specify a move like this:
return move(this->us);
then it works.
I have found multiple references indicating that a move should not be required - for example this SO question, and these guidelines from the chromium project.
My question is: why does the move need to be explicitly specified in this case? Is it related to fact that I am returning the value of an instance variable somehow?
Apologies in advance if this is a dupe - I feel sure it would have been asked before, but I struggle to come up with search terms that find it.