You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

对元素已被移动的std::vector执行resize操作是否合法?

C++标准对移动语义的基础约定是:被移动的对象处于「有效但未指定状态」,所有无前置条件的操作都可以合法调用,这是判断所有场景合法性的基础。

场景0

完全合法。移动后的vector执行赋值操作是标准明确允许的行为,赋值会直接覆盖原有未指定的状态,不存在任何风险。

std::vector<T> v(100, t);
f(std::move(v));
v = make_a_vector();

场景1

确实属于不合法代码。g接收vector的const左值引用,内部通常会执行读取vector大小、访问元素等有前置条件的操作,而移动后的vector状态未指定,无法满足这些操作的前置要求,会触发未定义行为。

std::vector<T> v(100, t);
f(std::move(v));
g(v);

场景2

合法。std::vector::resize 是无前置调用要求的成员函数,无论移动后的vector当前处于哪种有效状态,resize都可以正常执行:如果移动后vector为空,resize会直接分配新空间;如果移动后vector仍持有元素,resize会按需销毁多余元素或新增元素,全程由vector自身管理生命周期,没有安全问题。

std::vector<T> v(100, t);
f(std::move(v));
v.resize(120);

场景3(核心疑问)

只要你的类型T符合C++标准对容器元素的常规要求,这段代码完全合法,不会触发未定义行为,理由如下:

  1. std::make_move_iterator 只是把普通迭代器包装成返回右值引用的迭代器,h遍历范围时如果对元素执行移动构造/赋值操作,只会让原vector内的元素进入「有效但未指定」状态,这本身是符合标准约定的。
  2. vector::resize 对原有元素的操作只有两类:要么是销毁元素(缩容场景),要么是移动/拷贝元素到新分配的内存(扩容场景)。而C++标准要求所有可放入容器的类型,都必须支持对被移动对象执行销毁、移动赋值操作,这些操作都是无前置条件的合法操作。
  3. 唯一的例外是自定义类型T本身违反标准约定,被移动后执行销毁/移动操作会触发异常或错误,这属于类型实现的bug,和vector的resize操作无关。
std::vector<T> v(100);
h(std::make_move_iterator(v.begin()), std::make_move_iterator(v.end()));
v.resize(120);

相关函数签名

template<class T> void f(std::vector<T>&&); 
template<class T> void g(std::vector<T> const&);
template<class It> void h(It first, It last);

内容的提问来源于stack exchange,提问作者alfC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 01:27:06