【发布时间】:2017-11-07 22:09:05
【问题描述】:
考虑下面的代码。
using T = std::string;
void rotate_left(std::vector<T>& v) {
T temp = std::move(v[0]);
for (size_t i=0; i+1 < v.size(); ++i) {
v[i] = std::move(v[i+1]);
}
v.back() = std::move(temp);
}
int main()
{
std::vector<T> v(3); // a vector of three Ts
T x = std::move(v[1]); // move-from the second element
rotate_left(v);
// Can we now say that v[0] is in a moved-from state, or did we
// get undefined behavior when we moved from v[1] a second time?
}
rotate_left 函数实际上只是将向量中的所有内容向下移动一个位置(然后将第一个元素放在末尾)。我的问题是,当向量中的一个元素处于“已移出状态”时,此函数是否已定义行为?
这与“自移动”相关但不完全相同。在这种情况下,我们从一个被移动的对象移动到另一个被移动的对象,我的问题是我们是否可以依靠这个让两个对象仍然处于某个被移动的状态,或者“赋值来自”是否是“具有先决条件”的操作之一,因此不能用于任意移出的对象。
我很清楚
- 这对于像
unique_ptr这样的健全的库类型来说非常好 - 这个如果我定义合理的话,对于我自己的用户定义类型来说非常好
- 如果我疯狂地定义它们,这将对我自己的用户定义类型有问题
- 这对于我在 libstdc++ 和 libc++ 上尝试过的所有库类型都很好
所以我真正想要的是:
- 标准中的具体措辞证明这必须完全适用于所有 STL 类型,或者
- 一个 STL 或 Boost 类型“在野外”的具体示例,其中此代码肯定有问题
我从this bug 推断出_GLIBCXX_DEBUG 会检查self-move,但我可以确认它不会检查move-from-moved;这是因为他们认为 move-from-moved 是安全且合法的,还是只是因为还没有人编写代码来检查它?
【问题讨论】:
-
不是一个答案,因为语言律师,但我希望有效但未指定的价值得到转移
-
这种棘手。在 C++11 及更高版本中,
vector仅要求T可擦除,但您正在寻找的保证适用于 MoveConstructable/MoveAssignable @987654322 的对象@
标签: c++ language-lawyer move-semantics