When I use reset to rebind the unique_ptr
, something bad happens but when use std::make_unique
, everything is ok.
int main() {
unique_ptr<string> p= nullptr;
auto l=[&p]()->void{
static string x {"1111"};
cout<<x<<endl;
//p = std::make_unique<string>(x);// compile ok
p.reset(&x);//compile error free():invalid pointer;
cout<<p.get()<<endl;
return;
};
l();
cout<<p->length()<<endl;
cout<<p.get()<<endl;
return 0;
}
I think that when the reset method is called, the string object is not really handed over to the unique_ptr
management. When leaving the scope, the dtor is called twice
Both variants do compile without errors (provided one adds the missing parts). Your code invokes undefined behavior and likely crashes at runtime.
When you use std::make_unique
like this:
p = std::make_unique<string>(x);
Then std::make_unique
constructs a std::unique_ptr
that manages the lifetime of a std::string
that is constructed as a copy of x
. You now have two strings, x
and the one managed by p
.
When you use reset
like this:
p.reset(&x);
You tell p
to take ownership of x
. However, x
is not dynamically allocated. It makes no sense to transfer its ownership to a smart pointer. When p
s destructor is called it will attempt to delete &x
but x
was not allocated via new
, hence there is undefined behavior. When the program terminates the lifetime of the static string ends and x
is destroyed (again).
I think that when the reset method is called, the string object is not really handed over to the unique_ptr management.
Yes it is. And that is the problem.
It is not clear what the actual purpose of the code is. To return string from the lambda:
#include <string>
#include <iostream>
int main() {
auto l=[](){
std::string x {"1111"};
std::cout << x << std::endl;
return x;
};
auto p = l();
std::cout << p.length() << std::endl;
}