实现resize
的所有STL容器都使用副本来填充新元素,即使副本的源是默认的构造对象?
为什么这样做?
我认为没有任何优势和成本。
作为背景,我在寻找a random access container for elements that can't be copied时遇到了这个问题:
答案 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 ++标准的设计者并没有经常遇到你的用例,认为值得抽象。