考虑以下代码:
std::vector vec;
vec.reserve(500);
size_t cap = vec.capacity();
std::vector newVec = std::move(vec);
assert(cap == newVec.capacity());
在您遇到的几乎任何实现中,这都会起作用。我不在乎实现是做什么的。我想知道标准要求什么。搬家的vector
容量和原来的一样吗?还是断言会触发?
考虑以下代码:
std::vector vec;
vec.reserve(500);
size_t cap = vec.capacity();
std::vector newVec = std::move(vec);
assert(cap == newVec.capacity());
在您遇到的几乎任何实现中,这都会起作用。我不在乎实现是做什么的。我想知道标准要求什么。搬家的vector
容量和原来的一样吗?还是断言会触发?
查看标准,移动构造函数似乎不需要任何东西,但是正如@amaurea 所说,如果移动构造函数尝试分配或释放内存,它将完全违背移动语义的目的,所以我希望容量在所有实现中保持不变。
23.2.1 一般容器要求
表达
X u(a);
X u = a;
断言/注释前置/后置条件
要求:T
是否可 CopyInsertable 到 X 中(见下文)。
邮政:u == a
该标准仅要求newVec == vec
. 由于不考虑容量std::vector::operator==
,newVec
所以不一定要具有相同的容量vec
。
移动构造函数的 C++11 标准要求std::vector
是(表 99 - 分配器感知容器要求):
X(rv)
X u(rv)
rv
帖子:你应该有与此构造之前相同的元素;的值get_allocator()
应与rv.get_allocator()
本次施工前的值相同。这里对容量没有要求/保证。但是我们可以得出结论,恒定的复杂性隐含地否认了任何重新分配。除了重新分配之外,我看不到任何其他改变容量的合乎逻辑的理由。所以应该是一样的。
从另一个角度来看,如果移动的向量是空的,那么忽略它并默认构造本身是完全合法的。这仍然是 O(1),因为它不需要任何每个元素的构造。(感谢Nicol Bolas的这个问题)。
实现也可能使用函数hint
参数将容量缩小到大小std::allocator::allocate
:
pointer allocate(size_type, allocator<void>::const_pointer hint = 0);
未指定使用hint
,但如果实现需要,则旨在帮助本地化。所以一些复杂的解决方案可能会传递向量存储指针hint
并使用realloc
它来缩小容量。
结论:看起来标准并不能保证移动时保持容量std::vector
,存储可能会缩小。