为什么STL容器使用复制来填充调整大小?

时间:2010-08-19 01:08:13

标签: c++ stl design-choices

实现resize的所有STL容器都使用副本来填充新元素,即使副本的源是默认的构造对象?

为什么这样做?

我认为没有任何优势和成本。


作为背景,我在寻找a random access container for elements that can't be copied时遇到了这个问题:

4 个答案:

答案 0 :(得分:3)

节省了复杂性。我们当然需要复制构造案例,默认构造可以建模为复制默认构造的对象。

性能损失可以忽略不计。写入零与复制零的速度大致相同。兼容性惩罚为零,因为无论如何所有容器都需要可复制性。另一方面,默认构造不是必需的。

如果您确实想要将标准容器与不可复制的对象一起使用,请使用emplace查看C ++ 0x和就地构造。但是,没有方法可以同时emplace多个元素。 (如果您使用的是deque,则emplace循环与resize的性能不会相差很多。)

答案 1 :(得分:1)

在你的情况下,也许你最好将指针存储到容器中的那些对象 - 可以复制指针。

关于在容器中复制;有什么选择?如果您不得不重新分配新的内存块来存储正在存储的内容,那么您必须以某种方式获取现有数据!

答案 2 :(得分:0)

我能想到这种行为的唯一原因是容器支持插入和插入需要一个副本。您应该能够以类似于默认构造新元素的deque(分页和非连续)的方式创建支持调整大小的容器。但是,您必须禁止分配整个容器以及插入元素 - 您可以修改集合中构造的对象。

我的猜测是,没有人看到需要不支持插入的集合,也没有实现值类型复制。另外请注意,您可能应该在关闭之前将其标记为wiki;)

答案 3 :(得分:0)

标准容器在值类型上定义了CopyConstructible和Assignable的要求,这些要求足以支持容器和序列上的所有操作(您可能还希望它们与关联容器具有可比性,但即使这样也不是必需的因为你可以改为提供比较器。

你要求的是对一组操作有一组要求,包括容器的一部分加上来自Sequence的东西(即那些从不重新定位其内容的容器上的1-参数resize()operator[]clear()和除*it = t之外的迭代器接口),以及其余的另一组要求。标准库更喜欢以相反的方式执行此操作:选择几乎涵盖所有内容的通用需求集,然后对少量功能有额外要求(例如要求默认构造以调用{{1}没有指定第二个参数)。

容器本身并没有考虑到你的特定操作集 - 复制和分配是他们设计要做的事情的固有内容,即包含放入其中的值,所以我推测在Stepanov的思想中这不是“一点点功能”。因此,更广泛的要求是因为抽象容器大于您提出的ResizeableCollectionOfDefaultConstructedObjects。实际上,带走resize()和CollectionOfDefaultConstructedObjects几乎只是一个数组。我想STL和C ++标准的设计者并没有经常遇到你的用例,认为值得抽象。