1

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

为什么这样做?

我认为没有优势和一些成本。


作为上下文,我在寻找无法复制的元素的随机访问容器时遇到了这个问题:

4

4 回答 4

3

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

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

如果您真的想使用带有不可复制对象的标准容器,请查看 C++0x 并使用emplace. 但是,没有办法同时处理emplace多个元素。(如果您使用的是,那么循环deque应该不会有太多的性能损失。)emplaceresize

于 2010-08-19T02:06:12.433 回答
1

在您的情况下,也许您最好将指向这些对象的指针存储在容器中——可以复制指针。

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

于 2010-08-19T01:14:05.343 回答
0

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

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

于 2010-08-19T01:20:51.717 回答
0

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

您要求的是对一组操作有一组要求,这些操作由 Container 的一部分加上 Sequence 中的一些内容(即resize()那些从不重新定位其内容的容器上的1 参数operator[]clear()以及迭代器接口不包括*it = t) ,以及对其余部分的另一组要求。标准库更喜欢这样做:选择一组涵盖几乎所有内容的通用要求,然后对少量功能有附加要求(例如要求默认可构造以便在resize()不指定第二个的情况下调用范围)。

容器的构思并没有考虑到您的特定操作集 - 复制和分配是它们的设计目的所固有的,即包含放入其中的值,所以我推测在 Stepanov 的想法中不是“一点点功能”。因此存在更广泛的要求,因为抽象 Container 比您建议的 ResizeableCollectionOfDefaultConstructedObjects 大。事实上,resize()CollectionOfDefaultConstructedObjects 几乎只是一个数组。我猜 STL 和 C++ 标准的设计者并没有经常遇到您的用例,以至于认为它值得抽象。

于 2010-08-19T02:07:22.403 回答