具有临时对象的 Fundamenta 数据类型赋值运算符

Fundamenta data type assignment operator with temporary objects

本文关键字:数据类型 赋值运算符 Fundamenta 临时对象      更新时间:2023-10-16

你好,所以我试图了解引擎盖下发生了什么。

int* puter;
puter = std::make_unique<int>(50).get();
if(puter) { std::cout << *puter << std::endl; }

起初,我认为推杆应该是一个悬空的 ptr,因为来自make_unique的临时unique_ptr会随着分配的资源一起被摧毁。但事实并非如此。 过了一会儿,我明白了,如果将unique_ptr资源分配给推杆,可能不会发生这种情况。 但真正的问题是。我什么时候应该假设事情会从临时中转移?有规则吗?在这种情况下,我应该只使用释放方法来保证吗?

正如其他人所提到的,这实际上会触发未定义的行为。

你最初的想法正是发生的事情

起初我认为推杆应该是一个悬空的 ptr,因为来自make_unique的临时unique_ptr会随着分配的资源一起被摧毁

因此

if(puter) { std::cout << *puter << std::endl; }

导致未定义的行为 - 你不知道那里有什么,不同的编译器和机器可以有不同的结果(例如,可以是 50,可以是 0,可以是 nullptr,或者一些垃圾值......

但真正的问题是。我什么时候应该假设事情会从临时中转移?有规则吗?在这种情况下,我应该只使用释放方法来保证吗?

这取决于类型/类是否支持移动语义(即定义了移动构造函数/移动赋值运算符)。如果没有,则与复制相同。

在这种情况下,int* 是基元类型,基元类型没有移动构造函数/赋值,因此临时赋值不会是移动赋值。

另一方面,如果你将一个临时的 std::vector 分配给另一个 std::vector,移动赋值将被调用,因为 std::vector 类有一个定义良好的移动赋值运算符(和一个移动构造函数)。

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