对于std :: vector的副本分配,当源的大小小于目标的容量时,是否允许重新分配存储和容量缩减?或者是否保证不会发生重新分配/收缩(即始终遵守先前的保留())?
另一方面,如果源的大小大于目的地的容量并且发生了重新分配,是否需要重新分配尊重源的容量(例如,目的地的新容量应不小于源的容量,或者甚至要求它们是相同的)?或者重新分配只是完成其工作(基于新的大小)而不考虑源的容量?
至于移动分配,我认为不会进行存储重新分配(虽然我未能在标准中找到相关部分),所以它是否意味着目标新容量的值与源的旧容量完全相同?我可以期望v = vector<T>{};
与vector<T>{}.swap(v);
具有相同的效果吗?
我认为答案被埋在标准的某个地方,但我却找不到它们。 (如果C ++ 11和C ++ 03的内容不同,我想知道两者的各种要求。)
PS:对于上述问题的答案,对于std :: string是否相同(仅在C ++ 11中,这意味着连续存储而且没有COW,C ++ 03字符串不在雷达中)?< / p>答案 0 :(得分:3)
std::vector<T,A>( std::vector<T,A>&& )
这保证是恒定时间(N3797表99 X u(rv)
)。
我自己不知道在没有将指针移动到缓冲区的情况下在恒定时间内移动任意大小的向量。如果这个(没有办法)是真的,那么构造的向量必须有一个至少与源缓冲区一样大的缓冲区。标准中没有措辞表明vector
需要有效,但是:右侧vector
可以将其容量减少到大于或等于size
的任何值:后置条件只是元素是相同的。理论上它甚至可能是更大的容量,如果右侧vector
具有编译器选择以任何理由暴露的“隐藏容量”(比如月亮的阶段)。
N3797标准中的任何一点都不是放在任何容器上的capacity
的上限。符合要求的实现可以使所有std::vector
具有至少200万个元素容量(禁止allocator
失败 - 可用于强制容量0
),无需操作减少该值低于200万。 (shrink_to_fit
只是一个建议,std::vector<T,A>().swap(x)
可以创建一个200万容量的vector
并交换它。
由于以上大部分都是否定形式,我只能在每次提及vector
,allocator
,allocate
和capacity
时搜索标准。 capacity
永远不会以任何一点的上限来描述。在空allocator
构造函数中对std::vector
的额外调用没有限制(异常安全除外)(如果allocator
失败,则可能必须保持0和容量0 ,但将该状态提取到任何不使用相同allocator
的东西都具有挑战性。)
对于副本分配和移动分配,副本分配不保证超出最基本的容量(capacity() >= size()
)。
对于移动分配,它取决于它的适用方式:
23.2.1 [container.requirements.general] / 10
表96和表99中的除非另有说明(显式或通过根据其他函数定义函数),调用a 容器成员函数或将容器作为参数传递给库函数不应无效 迭代器,或更改该容器中对象的值。
a = rv
(又名std::vector<T,A>& operator=(std::vector<T,A>&&)
)案例与我们有关。既没有提到rv
中包含的值被破坏,也没有提到它们的迭代器被无效。因此,根据23.2.1 / 10,迭代器不会失效。
但是,这并不要求移动缓冲区。缓冲区从rhs移动到lhs,或者在rhs vector
中保持不变。表99隐含地提到了lhs项可以移动分配给(这是std::array
可以工作的唯一方式)。
由于std::array
别无选择,只能移动元素,而std::vector
没有进一步保证移动缓冲区,因此不必移动缓冲区。但是,移动缓冲区似乎是合法的实现。
在实践中,std::vector<T,A>( std::vector<T,A> const& )
会将右侧内容的副本执行到左侧,并且在我检查过的每个实现中,左侧的capacity
等于{结果size
的{1}}。同样,vector
会产生一个恰好适合其输入的std::vector<T,A>( ForwardIterator, ForwardIterator )
。
请注意,vector
在复杂性方面保持线性。
答案 1 :(得分:1)
我在标准中找不到任何可以分配的内容
一个具有足够容量以降低容量的载体。
如果我在作业之前完成reserve
,我保证
只要重新分配,迭代器就不会失效
向量永远不会超过我保留的容量。
移动分配的问题是特别的。没有 似乎是任何特殊情况允许它使迭代器无效 (除非来源大于 目的地),但这种打败了移动的目标 分配。我怀疑这是标准中的缺陷。
编辑:
对于a = rv
(其中a
而言,表96中的值是多少
一个容器,rv
是同一类型的非const r值
容器),标准给出线性复杂性,并说
“将所有现有元素a
移动分配给或
显然,标准的意图是
能力不降低;执行时间的好处
move仅适用于单个元素,而不适用于容器
本身。
答案 2 :(得分:0)
回答你的PS:
至少对于std::string
,你不能假设字符串的处理类似于处理字符向量。
COW(Copy-on-Write)不是实现字符串的必需品,并非所有库实现都这样做。