std::move指向元素后迭代器的有效性:未定义行为还是合法行为?
std::move后调用std::list::erase是否合法?
问题场景
以下代码中,对std::list迭代器指向的元素执行std::move后,调用erase移除该元素的行为是否属于未定义行为,还是符合C++标准的定义良好行为?
// 假设T支持移动语义 void sink(T&& t) { // 一些操作 } std::list<T> list = getSomeList(); for (auto it = list.begin(); it != list.end(); ) { if (some_pred) { sink(std::move(*it)); it = list.erase(it); // std::move之后调用erase是否合法? } else ++it; }
结论与解释
这个行为是完全符合C++标准的定义良好行为,理由如下:
- std::move本质只是类型转换工具,它不会修改原对象的内存位置、容器结构,也不会使指向该元素的迭代器失效。仅将左值
*it转换为右值引用,允许后续操作通过移动语义转移对象资源。 - 被移动后的T对象会处于合法但未指定的状态,但C++标准明确要求:任何类型在移动操作完成后,必须保证对象可以被安全析构——而std::list::erase的核心动作就是销毁迭代器指向的元素,完全符合要求。
- std::list::erase的前置条件仅要求传入的迭代器指向容器内的有效元素(非end()迭代器),这里的it在std::move之后依然指向原有效元素,满足erase的调用要求。
- 只要sink函数内部没有修改std::list本身(比如移除元素),迭代器it就会保持有效,直到erase调用完成(erase会返回下一个有效迭代器,这也是代码中
it = list.erase(it)写法正确的原因)。
内容的提问来源于stack exchange,提问作者Santiago
相关产品推荐
相关产品推荐

