是否x = std::move(x)未定义
Is x = std::move(x) undefined?
设x
为已初始化的某种类型的变量。
x = std::move(x)
定义?这在标准中处于什么位置,它是怎么说的?
不,这不是未定义行为,它将是实现定义的行为,它将取决于如何实现move赋值。
与此相关的是LWG问题2468:库类型的自移动分配,注意这是一个活跃的问题,没有官方提案,所以这应该被认为是指示性的,而不是决定性的,但它确实指出了标准库所涉及的部分,并指出它们目前存在冲突。它说:
假设我们写
vector<string> v{"a", "b", "c", "d"}; v = move(v);
v的状态应该是什么?标准上什么也没说具体到自移动分配。有几个是相关的文本部分标准,但不清楚如何协调它们。
[…]
从文本中不清楚如何将这些片段组合在一起,因为不清楚哪个优先。可能是17.6.4.9 [res.on]。(它强加了一个隐含的先决条件,在MoveAssignable需求中没有提到,所以v = move(v)是未定义的),或者23.2.1 [container.requirements]。general]获胜(它显式地为Container::operator=提供了额外的保证,超出了一般标准库函数的保证,因此v = move(v)是无操作的),或者可能是其他的东西。
在我检查的现有实现中,不管它的价值是什么,v = move(v)似乎清除了向量;它没有保持矢量不变,也没有导致崩溃。
并提出:
注意,对于内置类型,这基本上是一个拷贝,我们可以从c++ 14标准草案非正式地:改变MoveAssignable和Container需求表(以及任何其他提到move赋值的需求表,如果有的话),使其明确x = move(x)是定义的行为,它使x处于有效但未指定的状态。这可能不是今天的标准说的,但这可能是我们想要的它与我们告诉用户的和实现实际做的是一致的。
5.17
[express .ass]:
看到在简单赋值(=)中,表达式的值替换左边所引用对象的值操作数。
这与类的情况不同,其中5.17
表示:
注意,clang有一个自我移动警告:如果左操作数为类类型,则该类完成。定义了对类对象的赋值通过复制/移动赋值操作符(12.8,13.5.3)。
日志:给Clang添加一个新的警告,- self-move。
- self-move类似于- self-assign。在以下情况下触发此警告试图将值移动到自身。参见r221008会被这个警告抓住。
它将调用X::operator = (X&&)
,因此由实现来管理这种情况(就像X::operator = (const X&)
一样)
调用X::operator=(X&&)
(左值限定为" *this
")。
在基本类型上,std::move
没有什么作用,并且根本不与=
交互。所以这只适用于类类型的对象。
现在,对于std
中的类型(或由其模板之一生成的类型),move
d中的对象往往处于未指定(但有效)的状态。这不是未定义的行为,但不是有用的行为。
必须检查每个给定X::operator=(X&&)
的语义,检查std
中的每个类型对于堆栈溢出答案来说"太宽泛"。他们甚至可能自相矛盾。
一般来说,当move
从一个对象中返回时,你是在告诉消费者"你不关心对象之后处于什么状态"。因此,使用x = std::move(x)
是不礼貌的,因为您(通常)确实关心操作完成后x
处于什么状态(当您为其赋值时)。在同一操作中,将同一对象既用作左值又用作右值,这不是一个好做法。
std::swap
,它是这样的:template<class T>
void swap(T& lhs, T& rhs) {
T tmp = std::move(lhs);
lhs = std::move(rhs);
rhs = std::move(tmp);
}
中间行lhs = std::move(rhs)
,如果在同一对象上调用两次swap,则执行x = std::move(x)
。
请注意,我们并不关心x
在这一行完成后处于什么状态;我们已经在tmp
中存储了x
的状态,我们将在下一行恢复它。
- 编译C++时未定义的引用
- vscode g++链路故障:体系结构x86_64的未定义符号
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- 不知道某个东西是否被忽略会引入未定义的行为吗
- 对C宏的未定义引用,但在定义它时会出现重新定义错误
- 未定义的引用在哪里
- 编译时的 CImg 库返回对"__imp_SetDIBitsToDevice"的未定义引用
- 对Py_Initialize()的未定义引用
- c++11评估顺序(未定义的行为)
- 使用mysql c++连接器的未定义引用
- 是否可以在 C++03 中定义'move-and-swap idiom'等效项
- 从python调用openMP共享库时,未定义opnMP函数
- 在 Mac 上使用 CMAKE 将 FFTW 和 FFTWPP 链接到项目中时未定义的符号
- Cmake 链接问题:未定义对 Button::mousePressEvent(QGraphicsSceneMouseE
- 未定义的引用 .. 使用 OpenCV 编译 C++ 代码时,从命令行
- 具有外部"c"和程序集的未定义函数
- 为什么 std::move 未定义,尽管编译器使用 -std=c++11 调用
- std::move的未定义行为
- 是否x = std::move(x)未定义