这个C++代码会一直像我期望的那样工作吗,还是执行顺序没有保证



好吧,我有一些代码似乎可以工作,但我不确定它是否总是能工作。我正在使用类的一个成员作为映射键将unique_ptr移动到stl映射中,但我不确定在某些情况下移动是否会使指针无效。

代码如下:

struct a
{
std::string s;
};
std::map<std::string, std::unique_ptr<a>> m;
std::unique_ptr<a> p = std::make_unique<a>();
// some code that does stuff
m[p->s] = std::move(p);

因此,目前这似乎有效,但在我看来,在字符串用作映射键之前,p可能会变得无效,这将导致内存异常。显然,我可以在移动之前创建一个临时字符串,也可以通过迭代器进行分配,但如果没有必要,我宁愿不这样做。

此代码具有定义良好的行为。

在C++17中,std::move(p)将在m[p->s]之前进行评估。在C++17之前,std::move(p)可以在m[p->s]之前或之后进行评估。但是,这并不重要,因为std::move(p)不会修改p。实际导致p从中移出的只是分配。

被调用的赋值运算符具有签名

unique_ptr& operator=(unique_ptr&& other);

并且被调用

m[p->s].operator=(std::move(p));

这意味着,在进入operator=主体之前,保证不会对p进行修改(other参数的初始化仅为引用绑定(。当然,在评估对象表达式m[p->s]之前不能输入operator=的主体。

因此,您的代码在所有版本的C++中都是定义良好的。

代码很好。在C++17中,我们在排序上得到了强有力的保证,这使得这个代码100%可以

在C++17之前,标准具有

在所有情况下,赋值都是在右操作数和左操作数的值计算之后,赋值表达式的值计算之前进行的。

但这仍然意味着代码是可以的。我们不知道m[p->s]std::move(p)中的哪一个先发生,但由于move实际上对p没有任何作用,因此p->s将是有效的,并在p移动到m[p->s]之前得到解决

最新更新