您好,我正在努力了解幕后发生了什么。
int* puter;
puter = std::make_unique<int>(50).get();
if(puter) { std::cout << *puter << std::endl; }
起初我认为计算机应该是一个悬空的ptr,因为make_unique中的临时unique_ptr将与分配的资源一起被销毁。但事实并非如此。 过了一会儿,我可以理解,如果将unique_ptr资源移动分配给puter,可能不会发生这种情况。 但真正的问题是。什么时候我应该假设事情将从临时转移?它有规则吗?在这种情况下,我应该只使用发布方法来保证吗?
答案 0 :(得分:0)
正如其他人所提到的,这实际上会触发未定义的行为。
你最初的想法正是发生了什么
起初我认为计算机应该是一个悬空的ptr,因为make_unique中的临时unique_ptr将与分配的资源一起被销毁
因此,
if(puter) { std::cout << *puter << std::endl; }
导致未定义的行为 - 你不知道那里有什么,不同的编译器和机器可以有不同的结果(例如可以是50,可以是0,可以是nullptr,或者一些垃圾值......)
但真正的问题是。什么时候我应该假设事情将从临时转移?它有规则吗?在这种情况下,我应该只使用发布方法来保证吗?
这取决于类型/类支持是否移动语义(即定义了移动构造函数/移动赋值运算符)。如果没有,则与复制相同。
在这种情况下,int *是一个基本类型,而原始类型没有移动构造函数/赋值,因此赋值临时不会移动赋值。
另一方面,如果将临时std :: vector分配给另一个std :: vector,则会调用移动赋值,因为std :: vector类具有定义明确的移动赋值运算符(以及移动构造函数)。 e.g。
std::vector<int> v;
v = std::vector<int>{1,2,3}; //RHS is a temporary object, so it will call the vector's move assignment operator