【发布时间】:2018-08-17 09:30:44
【问题描述】:
如果我将一个向量分配或复制到另一个向量(其容量与前者的大小相同或更大),我可以假设后者的缓冲区将被重用吗?
下面的例子表明我可以,但是,它是由标准保证的吗?
在这方面std::vector::assign 和std::vector::operator= 的行为有什么区别吗?
#include <vector>
#include <iostream>
#include <cassert>
int main()
{
std::vector a {1, 2, 3, 4, 5};
std::vector b {1, 2, 3, 4};
std::vector c {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::cout << "1 ==== " << a.capacity() << " " << a.data() << std::endl;
const auto* pa = a.data();
a = b;
assert(pa == a.data());
std::cout << "2 ==== " << a.capacity() << " " << a.data() << std::endl;
a = c;
assert(pa != a.data());
std::cout << "3 ==== " << a.capacity() << " " << a.data() << std::endl;
}
更新:This answer 提到
void assign(size_type n, const T& t);
等价于
erase(begin(), end());
insert(begin(), n, t);
标准真的是这样制定的吗?它是否适用于std::vector::assign的所有重载?
【问题讨论】:
-
通常是的,但它实际上取决于分配器的兼容性和分配器的传播:如果分配器没有在分配时传播,或者源分配器可以释放目标分配器的内存,那么目标缓冲区被重用( target => 赋值运算符右侧,source=> 赋值运算符左侧)。
-
抱歉,我在最新草稿中找不到与“提到的这个答案”相关的任何内容。标准(据我所知)只说“用 t 的 n 个副本替换 a 中的元素。无效...”参见 [eel.is/c++draft/…
-
或许可以用
vector::reserve()上的要求来证明这一点。类似于:在赋值之前插入一个a.reserve(a.size());,并且赋值可能会受到reserve() 的约束以使用相同的存储(例如,a[0] 的迭代器保证保持有效)。v.reserve(v.size());显然是一个空操作,并且始终适用于一个向量,。但我现在没有时间跟踪标准参考。 -
另请注意,如果分配器不在复制构造上传播,则原始缓冲区已经(保证)将被释放。
-
@L.F.那么
assign比operator=好,不是吗?
标签: c++ c++14 language-lawyer c++17