C++ 移动std::vector时是否需要保留容量?
考虑以下代码:C++ 移动std::vector时是否需要保留容量?,c++,c++11,stdvector,language-lawyer,move-semantics,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()); 在您遇到的几乎所有实现中,这都是可行的。我不在乎实现做什么。我想知道标准要求什么。移动到向量的容量是否与原始向量相同?或者断言会触发吗?看看标准,似乎移动构造函数不需要任何东西,但是正如@amaurea所说,如
std::vector vec;
vec.reserve(500);
size_t cap = vec.capacity();
std::vector newVec = std::move(vec);
assert(cap == newVec.capacity());
在您遇到的几乎所有实现中,这都是可行的。我不在乎实现做什么。我想知道标准要求什么。移动到
向量的
容量是否与原始向量相同?或者断言会触发吗?看看标准,似乎移动构造函数不需要任何东西,但是正如@amaurea所说,如果移动构造函数尝试分配或释放内存,它将完全违背移动语义的目的,因此,我希望所有实现中的容量保持不变
23.2.1一般集装箱要求 表情 断言/注释前置/后置条件 要求:
T
可复制插入X(见下文)。post:
u==a
本标准仅要求
newVec==vec
。由于std::vector::operator=
未考虑容量,因此newVec
不必具有与vec
相同的容量std::vector
的C++11移动构造函数的标准要求是(表99-分配器感知容器要求):
- 分配器的移动构造不应通过异常退出
- 立柱:u应具有与施工前rv相同的构件;在此构造之前,
的值应与get\u分配器()
的值相同rv.get\u分配器()
- 复杂性:常数
std::allocator::allocate
函数的hint
参数将容量缩小到原来的大小:
pointer allocate(size_type, allocator<void>::const_pointer hint = 0);
指针分配(大小\类型,分配器::常量\指针提示=0);
未指定hint
的用法,但如果实现需要,则其目的是帮助实现局部性。因此,某些特定的解决方案可能会将向量存储指针作为hint
传递,并在其上使用realloc
来缩减容量
结论:看来标准并不能保证在移动时保持容量
std::vector
,存储空间可能会缩小。如果容量发生变化,这将彻底打破移动语义的最初动机,即避免不必要的复制和重新分配。不过,我手头没有标准,所以我不能给你一个正确的答案。“但我们可以得出结论,恒定的复杂性隐含着拒绝任何再分配。”+1看起来像实现一样,只会将容量减小到一定的大小,并且仍然满足所有法律要求,虽然这将是一种毫无意义的浪费。@aschepler:但是std::allocator
接口的哪一部分可以在封面下使用realloc
?@Rost:这里的问题是,既然vec
是空的,那么newVec
忽略从对象移动的空对象和默认构造本身是完全合法的。这仍然是O(1),因为它不需要任何每元素构造。@Peter Alexander噢,我终于看到了。但是,等等!在堆栈上和通过分配:运算符new(size\u t)
不是相同的可观察行为!你回答的第一段与最后一段中的警告相矛盾,因此很难说你的断言更有力。
X(rv)
X u(rv)
pointer allocate(size_type, allocator<void>::const_pointer hint = 0);