UPDATE 2: This bug has been fixed in Clang in r191150. GCC rejects the code with the correct error message.
UPDATE: I sent a bug report. The following code on my machine with clang ++ 3.4 (trunk 191037)
#include <iostream> #include <memory> int main() { std::unique_ptr<int> u_ptr(new int(42)); std::cout << " u_ptr.get() = " << u_ptr.get() << std::endl; std::cout << "*u_ptr = " << *u_ptr << std::endl; auto s_ptr = std::make_shared<int>(std::move(u_ptr)); std::cout << "After move" << std::endl; std::cout << " u_ptr.get() = " << u_ptr.get() << std::endl; std::cout << "*u_ptr = " << *u_ptr << std::endl; std::cout << " s_ptr.get() = " << s_ptr.get() << std::endl; std::cout << "*s_ptr = " << *s_ptr << std::endl; }
prints this:
u_ptr.get() = 0x16fa010 *u_ptr = 42 After move u_ptr.get() = 0x16fa010 *u_ptr = 42 s_ptr.get() = 0x16fa048 *s_ptr = 1
As you can see, the unique_ptr element unique_ptr not been moved. The standard guarantees that it must be empty after it is moved. shared_ptr points to an invalid value.
It is strange that it compiles without warning, and valgrind does not report any problems, leak, lack of heap. Weird
The correct behavior is shown if I create s_ptr with shared_ptr ctor, taking rvalue ref instead of unique_ptr instead of make_shared :
#include <iostream> #include <memory> int main() { std::unique_ptr<int> u_ptr(new int(42)); std::cout << " u_ptr.get() = " << u_ptr.get() << std::endl; std::cout << "*u_ptr = " << *u_ptr << std::endl; std::shared_ptr<int> s_ptr{std::move(u_ptr)}; std::cout << "After move" << std::endl; std::cout << " u_ptr.get() = " << u_ptr.get() << std::endl; //std::cout << "*u_ptr = " << *u_ptr << std::endl; // <-- would give a segfault std::cout << " s_ptr.get() = " << s_ptr.get() << std::endl; std::cout << "*s_ptr = " << *s_ptr << std::endl; }
He prints:
u_ptr.get() = 0x5a06040 *u_ptr = 42 After move u_ptr.get() = 0 s_ptr.get() = 0x5a06040 *s_ptr = 42
As you can see, u_ptr is null after the move, as required by the standard, and s_ptr indicates the correct value. This is the correct behavior.
(original answer.)
He simply pointed out : "If Foo does not have a constructor that accepts std :: unique_ptr, it should not compile."
To expand it a bit: make_shared its arguments to the constructor of T. If T has no ctor that could accept that unique_ptr<T>&& is a compilation error.
However, this code can be easily fixed and get what you want ( online demo ):
#include <memory> using namespace std; class widget { }; int main() { unique_ptr<widget> uptr{new widget}; shared_ptr<widget> sptr(std::move(uptr)); }
The fact is that make_shared is the wrong thing to use in this situation. shared_ptr has a ctor that accepts unique_ptr<Y,Deleter>&& , see (13) in ctors shared_ptr .