Ответ 1
ОБНОВЛЕНИЕ 2: Этот bug был исправлен в Clang в r191150. GCC отклоняет код с правильным сообщением об ошибке.
ОБНОВЛЕНИЕ: Я отправил отчет об ошибке . Следующий код на моей машине с 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;
}
печатает это:
u_ptr.get() = 0x16fa010
*u_ptr = 42
After move
u_ptr.get() = 0x16fa010
*u_ptr = 42
s_ptr.get() = 0x16fa048
*s_ptr = 1
Как вы можете видеть, элемент unique_ptr
не был перемещен. Стандарт гарантирует, что он должен быть пустым после его перемещения. shared_ptr
указывает на неправильное значение.
Странно, что он компилируется без предупреждения, и valgrind не сообщает о каких-либо проблемах, утечке, отсутствии кучи. Weird.
Правильное поведение показано, если я создаю s_ptr
с shared_ptr
ctor, беря rvalue ref вместо unique_ptr
вместо 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;
}
Он печатает:
u_ptr.get() = 0x5a06040
*u_ptr = 42
After move
u_ptr.get() = 0
s_ptr.get() = 0x5a06040
*s_ptr = 42
Как вы видите, u_ptr
имеет значение null после перемещения, как требуется стандартным, и s_ptr
указывает на правильное значение. Это правильное поведение.
(оригинальный ответ.)
Как прост указал: "Если Foo не имеет конструктора, который принимает std:: unique_ptr, он не должен компилироваться".
Чтобы немного расширить его: make_shared
пересылает свои аргументы в конструктор T. Если T не имеет никакого ctor, который мог бы принять, что unique_ptr<T>&&
это ошибка компиляции.
Однако этот код можно легко исправить и получить то, что вы хотите (онлайн-демонстрация):
#include <memory>
using namespace std;
class widget { };
int main() {
unique_ptr<widget> uptr{new widget};
shared_ptr<widget> sptr(std::move(uptr));
}
Дело в том, что make_shared
- это неправильная вещь для использования в этой ситуации. shared_ptr
имеет ctor, который принимает unique_ptr<Y,Deleter>&&
, см. (13) в ctors shared_ptr
.