std::vector<T>::分配使用有效的子范围?
std::vector<T>::assign using a subrange valid?
我想将向量转换为该向量的子范围,例如通过删除第一个和最后一个值。 assign 成员函数的使用在此上下文中有效吗?
std::vector<int> data = {1, 2, 3, 4};
data.assign(data.begin() + 1, data.end() - 1);
// data is hopefully {2, 3}
Cppreference 表示
All iterators, pointers and references to the elements of the container are invalidated. The past-the-end iterator is also invalidated.
然而,这种失效似乎直到 end of assign。
才发生
为了安全起见,我可以使用以下内容,但它看起来更冗长:
std::vector<int> data = {1, 2, 3, 4};
data = std::vector<int>{data.begin() + 1, data.end() - 1};
// data is now {2, 3}
您的 link 引用的 __invalidate_all_iterators
函数只是一个调试工具。它不会 "cause" 使迭代器失效;它有效地报告迭代器已因先前的操作而失效。可能是此调试工具可能无法捕获由此分配引起的错误。
assign
的前提条件是迭代器不在同一个容器中。违反前提条件会导致未定义的行为。
标准报价(最新稿):
[sequence.reqmts] a.assign(i,j)
Expects: T is Cpp17EmplaceConstructible into X from *i and assignable from *i.
For vector, if the iterator does not meet the forward iterator requirements ([forward.iterators]), T is also Cpp17MoveInsertable into X.
Neither i nor j are iterators into a.
您的安全选择是正确的。
如果你想避免重新分配(记住会有未使用的 space 留下),如果你想避免复制(这对复杂类型很重要,对 int
), 那么以下应该是有效的:
int begin_offset = 1;
int end_offset = 1;
if (begin_offset)
std::move(data.begin() + begin_offset, data.end() - end_offset, data.begin());
data.erase(data.end() - end_offset - begin_offset, data.end());
我想将向量转换为该向量的子范围,例如通过删除第一个和最后一个值。 assign 成员函数的使用在此上下文中有效吗?
std::vector<int> data = {1, 2, 3, 4};
data.assign(data.begin() + 1, data.end() - 1);
// data is hopefully {2, 3}
Cppreference 表示
All iterators, pointers and references to the elements of the container are invalidated. The past-the-end iterator is also invalidated.
然而,这种失效似乎直到 end of assign。
才发生为了安全起见,我可以使用以下内容,但它看起来更冗长:
std::vector<int> data = {1, 2, 3, 4};
data = std::vector<int>{data.begin() + 1, data.end() - 1};
// data is now {2, 3}
您的 link 引用的 __invalidate_all_iterators
函数只是一个调试工具。它不会 "cause" 使迭代器失效;它有效地报告迭代器已因先前的操作而失效。可能是此调试工具可能无法捕获由此分配引起的错误。
assign
的前提条件是迭代器不在同一个容器中。违反前提条件会导致未定义的行为。
标准报价(最新稿):
[sequence.reqmts]
a.assign(i,j)
Expects: T is Cpp17EmplaceConstructible into X from *i and assignable from *i. For vector, if the iterator does not meet the forward iterator requirements ([forward.iterators]), T is also Cpp17MoveInsertable into X. Neither i nor j are iterators into a.
您的安全选择是正确的。
如果你想避免重新分配(记住会有未使用的 space 留下),如果你想避免复制(这对复杂类型很重要,对 int
), 那么以下应该是有效的:
int begin_offset = 1;
int end_offset = 1;
if (begin_offset)
std::move(data.begin() + begin_offset, data.end() - end_offset, data.begin());
data.erase(data.end() - end_offset - begin_offset, data.end());