x = std :: move(x)是否未定义? [英] Is x = std::move(x) undefined?

查看:87
本文介绍了x = std :: move(x)是否未定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

x为先前已初始化的某种类型的变量.是以下行:

Let x be a variable of some type that has been previously initialized. Is the following line:

x = std::move(x)

未定义?在标准中这在哪里,它怎么说呢?

undefined? Where is this in the standard and what does it say about it?

推荐答案

不,这不是未定义的行为,它将是实现定义的行为,这将取决于如何实现移动分配.

No, this is not undefined behavior, it is going to be implementation defined behavior, it will depend on how move assignment is implemented.

与此相关的是 LWG问题2468 :图书馆类型的自动分配,请注意,这是一个活跃的问题,尚无正式建议,因此应将其视为指示性的而非确定性的,但它确实指出了该标准涉及的部分库并指出它们当前存在冲突.它说:

Relevant to this is LWG issue 2468: Self-move-assignment of library types , note this is an active issue and does not have an official proposal so this should be considered indicative rather than definitive, but it does point out the sections that are involved for the standard library and points out they currently conflict. It says:

假设我们写

Suppose we write

vector<string> v{"a", "b", "c", "d"};
v = move(v);

v be的状态应该是什么?标准什么也没说 具体关于自我分配.有几个相关的文字 部分标准,目前尚不清楚如何调和它们.

What should be the state of v be? The standard doesn't say anything specific about self-move-assignment. There's relevant text in several parts of the standard, and it's not clear how to reconcile them.

[...]

目前尚不清楚如何将这些部分组合在一起,因为尚不清楚哪一个优先.也许17.6.4.9 [res.on.arguments]胜出(它强加了MoveAssignable要求中未提及的隐式前提,所以v = move(v)未定义),或者23.2.1 [container.requirements.general ]胜(它明确地为Container :: operator =提供了额外的保证,超出了一般库函数所能保证的保证,因此v = move(v)是无操作的),或者其他一些原因.

It's not clear from the text how to put these pieces together, because it's not clear which one takes precedence. Maybe 17.6.4.9 [res.on.arguments] wins (it imposes an implicit precondition that isn't mentioned in the MoveAssignable requirements, so v = move(v) is undefined), or maybe 23.2.1 [container.requirements.general] wins (it explicitly gives additional guarantees for Container::operator= beyond what's guaranteed for library functions in general, so v = move(v) is a no-op), or maybe something else.

在我检查过的现有实现中,值得考虑的是,v = move(v)似乎可以清除向量.它没有使向量保持不变,也没有导致崩溃.

On the existing implementations that I checked, for what it's worth, v = move(v) appeared to clear the vector; it didn't leave the vector unchanged and it didn't cause a crash.

并提出:

非正式地:更改MoveAssignable和Container需求表(以及提及移动分配的任何其他需求表,如果有的话),以明确表明x = move(x)是已定义的行为,并且x处于有效但未指定的状态.这可能不是标准今天所说的,但这可能是我们想要的,并且与我们告诉用户的内容以及实际执行的操作是一致的.

Informally: change the MoveAssignable and Container requirements tables (and any other requirements tables that mention move assignment, if any) to make it explicit that x = move(x) is defined behavior and it leaves x in a valid but unspecified state. That's probably not what the standard says today, but it's probably what we intended and it's consistent with what we've told users and with what implementations actually do.

注意,对于内置类型来说,这基本上是一个副本,我们可以从C ++ 14标准草案的5.17 [expr.ass] 中看到:

Note, for built-in types this is basically a copy, we can see from draft C++14 standard section 5.17 [expr.ass]:

在简单赋值(=)中,表达式的值替换了左边引用的对象的值 操作数.

In simple assignment (=), the value of the expression replaces that of the object referred to by the left operand.

与类情况不同,其中5.17表示:

which is different than the case for classes, where 5.17 says:

如果左操作数是类类型,则该类应是完整的.分配给一个类的对象 复制/移动分配运算符(12.8,13.5.3).

If the left operand is of class type, the class shall be complete. Assignment to objects of a class is defined by the copy/move assignment operator (12.8, 13.5.3).

请注意,c具有自行移动警告:

日志: 向Clang添加新的警告-Wself-move.

Log: Add a new warning, -Wself-move, to Clang.

-Wself-move与-Wself-assign类似.该警告在以下情况时触发 试图将一个值移至自身.有关错误,请参见r221008 会被这个警告抓住.

-Wself-move is similiar to -Wself-assign. This warning is triggered when a value is attempted to be moved to itself. See r221008 for a bug that would have been caught with this warning.

这篇关于x = std :: move(x)是否未定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆