这段 C++ 代码会一直按我预期的方式运行吗,还是不能保证执行顺序?
Will this C++ code always work as I expect, or is the execution order not guaranteed?
好的,我有一些代码似乎可以工作,但我不确定它是否会始终有效。我正在使用 class 的成员之一作为映射键将 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 中,,这使得这段代码 100% OK。
C++17 之前的标准有
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.
但这仍然意味着代码没问题。我们不知道 m[p->s]
和 std::move(p)
中的哪一个先发生,但是由于 move
实际上没有对 p
做任何事情,所以 p->s
将是有效的并且在 p
移动到 m[p->s]
之前解决
此代码具有明确定义的行为。
在 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));
这意味着p
的修改保证在进入operator=
的body之前不会发生([=的初始化21=] 参数仅仅是一个引用绑定)。当然,在评估对象表达式 m[p->s]
之前,无法输入 operator=
的主体。
所以你的代码在所有版本的 C++ 中都是明确定义的。
好的,我有一些代码似乎可以工作,但我不确定它是否会始终有效。我正在使用 class 的成员之一作为映射键将 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 中,
C++17 之前的标准有
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.
但这仍然意味着代码没问题。我们不知道 m[p->s]
和 std::move(p)
中的哪一个先发生,但是由于 move
实际上没有对 p
做任何事情,所以 p->s
将是有效的并且在 p
移动到 m[p->s]
此代码具有明确定义的行为。
在 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));
这意味着p
的修改保证在进入operator=
的body之前不会发生([=的初始化21=] 参数仅仅是一个引用绑定)。当然,在评估对象表达式 m[p->s]
之前,无法输入 operator=
的主体。
所以你的代码在所有版本的 C++ 中都是明确定义的。