C++中结构化绑定接收返回值时std::vector是拷贝还是移动?
问题背景
以下为实现维特比算法的代码:
std::pair<std::vector<index_t>, float> viterbi_get_optimal_path(const SoundGraph &g, SequenceIter s_first, SequenceIter s_last, index_t curr_index) { if (s_first == s_last) { return {std::vector<index_t>({curr_index}), 1.0f}; } std::vector<index_t> seq; float prob = 0.0f; for (const auto &[next_index, curr_sound] : g.edges(curr_index)) { if (curr_sound.sound_ == *s_first) { auto [res_seq, res_prob] = viterbi_get_optimal_path(g, std::next(s_first), s_last, next_index); if (res_prob > 0.0f && curr_sound.prob_ * res_prob > prob) { prob = curr_sound.prob_ * res_prob; std::swap(seq, res_seq); seq.push_back(curr_index); } } } return {seq, prob}; }
补充说明:
index_t是std::ptrdiff_t的别名。
核心疑问
请问如下代码行中,函数返回的std::vector<index_t>是发生了拷贝还是移动?
auto [res_seq, res_prob] = viterbi_get_optimal_path(g, std::next(s_first), s_last, next_index);
提问者初步判断该vector是被移动的,但无法完全确定。
解答
这里的std::vector<index_t>发生的是移动,不存在拷贝操作,逻辑非常明确:
- 这行代码用C17引入的结构化绑定接收函数返回的
std::pair纯右值,从C17标准开始,纯右值初始化对象时会强制做复制消除,根本不会生成临时的pair对象拷贝,返回的pair会直接在结构化绑定对应的内存位置构造完成,没有额外开销。 - 再看pair内部的vector:函数最后
return {seq, prob};里的seq是函数内部的局部自动存储期变量,完全符合移动构造的触发规则——返回局部同类型对象时,编译器会优先选择vector的移动构造函数来初始化pair的第一个成员,哪怕不做返回值优化(RVO),也绝对不会走拷贝构造逻辑。 - 最后结构化绑定的
res_seq本质就是构造好的pair内部那个vector的别名,绑定过程不会再对vector做任何拷贝或移动操作。
顺便提一句,循环里写的std::swap(seq, res_seq)本身也是基于vector的移动语义实现的,只会交换内部的数据指针、大小、容量三个核心字段,不会把vector存储的索引元素挨个拷贝,开销极低。
内容的提问来源于stack exchange,提问作者frozenca
相关产品推荐
相关产品推荐

