使用std::vector::Assign()将矢量的一部分分配给它自己

Assign part of a vector to itself using std::vector::assign()

本文关键字:一部分 它自己 分配 vector std Assign 使用      更新时间:2023-10-16

假设我有一个大小为10的向量(v1)。现在我只想保留部分元素,使用:
v1.assign(v1.begin() + 2, v1.begin() + 6);

我不确定的是,原始元素是否会在分配之前被销毁。如果他们首先被摧毁,那么我就不能依赖原始数据。

此页面似乎表示元素首先被擦除。然而,一个快速的实验告诉我数据被正确地分配给了它自己。

那么,当将向量的一部分分配给它自己时,会发生什么呢?

根据C++14标准表100——序列容器要求(除了集装箱)

表达式a.assign(i,j)有一个前提条件,即ij不是a的迭代器

v1.assign(v1.begin() + 2, v1.begin() + 6);

使用迭代器作为v1的迭代器,因此您违反了条件

如果你想重置向量以包含子范围,那么你可以将这些元素复制到一个临时向量中,然后将该临时向量分配回主向量。这应该是一个移动操作(C++11及以上版本),因此不需要进行额外的复制。

v = std::vector<decltype(v)::value_type>(v.begin() + 2, v.begin() + 6);

正如Benjamin Lindley和Barry在评论中指出的那样,我们可以使用std::copy并移动像这样的迭代器

std::copy(std::make_move_iterator(v.begin() + 2), std::make_move_iterator(v.begin() + 6), 
          std::make_move_iterator(v.begin()));

来自C++11标准:

23.3.6.2矢量构造函数、复制和赋值

template <class InputIterator>
void assign(InputIterator first, InputIterator last);

11效果:

erase(begin(), end());
insert(begin(), first, last);

换句话说,不要使用:

v1.assign(v1.begin() + 2, v1.begin() + 6);

当调用insert时,first将是一个无效的迭代器。