移动std :: vector时是否需要保留容量?

时间:2012-10-29 20:34:46

标签: c++ c++11 stdvector language-lawyer move-semantics

请考虑以下代码:

std::vector vec;
vec.reserve(500);
size_t cap = vec.capacity();

std::vector newVec = std::move(vec);
assert(cap == newVec.capacity());

在你遇到的任何实现中,这都可行。我不关心实现什么。我想知道标准需要什么。移动到vector的容量是否与原始容量相同?或者断言会触发吗?

2 个答案:

答案 0 :(得分:11)

看看标准,似乎移动构造函数不需要任何东西,但是正如@amaurea所说,如果移动构造函数尝试分配或释放内存,它将彻底打败移动语义的目的,所以我会期望所有实施中的容量保持不变。


23.2.1一般容器要求

表达

X u(a);
X u = a;

断言/注意前/后条件

要求:T是CopyInsertable到X(见下文) 发布:u == a


该标准仅要求newVec == vec。由于std::vector::operator==未考虑容量,newVec无需具有与vec相同的容量。

答案 1 :(得分:9)

std::vector的移动构造函数的C ++ 11标准要求是(表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时保留容量,存储可能会缩小。