为什么std::list<T>
的单个参数构造函数需要T
为默认构造类型?我的意思是以下代码无法编译。
struct Foo { // does not have default constructor.
Foo (int i) {}
}
int main(void) {
std::list<Foo> l(10);
}
似乎可以使用construct and destroy idioms,就像他们已经在std :: vector中完成的那样,尽管有更多的簿记列表类。
在相关的说明中,为什么列表中没有容量功能?您可以争辩说,这样的函数会预先支付内存分配成本,并在以后消除push_back
对象的开销。至少它会使两个STL序列容器的接口稍微更加一致。
答案 0 :(得分:5)
std :: list没有容量功能,因为没有意义;它永远不会像矢量那样调整大小。它的容量仅受可用内存的限制,这是不容易确定的。
根据你的要求,我认为你真的想要保留()。这是向量的一次性,因为它(非常)需要这样的东西;并没有特别要求在所有STL容器中使所有功能保持一致,特别是当它们对其他容器没有意义时。
您可以使用自定义分配器完成相同的效果。正如曼努埃尔建议的那样,看看提升。
答案 1 :(得分:4)
没有一般要求该类型是默认可构造的 - 它必须是可复制和可分配的。您的代码不起作用,因为您尝试创建一个包含10个项目的列表 - 它们必须以某种方式构造,因此必须使用默认构造函数 - 但仅限于此特定情况。如果您创建了一个空列表并添加到其中,则不会有这样的要求。
其他容器也是如此 - 尝试编译以下内容:
#include <vector>
struct A {
A( int x ) : z(x) {}
int z;
};
std::vector <A> a(10);
关于问题的第二部分,我只是观察到界面的一致性不是标准容器的主要设计标准 - 例如,没有意图一种类型的容器是“插入式” “替换另一个人。 Scott Meyers的书“Effective STL”中的第1和第2项对此进行了很好的讨论。
答案 2 :(得分:3)
Neil already answered the main question
另请注意,调用resize()时需要默认构造函数。
您可以通过提供指向对象的STL列表来规避这一点,但我想这已经很明显了。
在相关的说明中,为什么不拥有 列表中的容量功能?您可以 认为这样的功能会付出代价 内存分配成本预先和 以后消除开销 push_back对象。至少它会 制作两个STL的接口 序列容器略多 是一致的。
我想这里的问题是STL lists allow cross-list splicing。如果您想预先分配内存,请查看Boost Pool Allocator。
答案 3 :(得分:2)
原因在于,当您构造n个元素的列表(其中n是您在构造函数中使用的参数)时,该列表使用T()的副本填充其n个元素的结构。
答案 4 :(得分:0)
为什么是单个参数 std :: list的构造函数需要T. 是一个默认可构造类型?
因为这个构造函数 - 创建包含元素的列表(作为参数传递的数字)。每个元素的值都是默认值。您还可以使用带有两个参数的构造函数,对于包含元素的创建列表,这些元素将使用第二个元素值进行初始化。
在相关的说明中,为什么不拥有 列表中的容量功能?
没有意义,因为向列表添加新元素的成本比向量的情况要少得多。
std :: vector没有这样的 限制。我的问题是为什么不 使用相同的技术 (创造/破坏成语) std :: list也是?
这不是限制。因为如果您不使用此类构造函数,则不需要默认初始值设定项。矢量也是如此。
答案 5 :(得分:0)
所以你的问题确实是“为什么列表中没有预留和容量功能?”
答案是没有理由提前为列表预留内存 - 添加新元素永远不需要realloc&amp;复制现有元素时,不要求保存列表内容的内存是连续的,并且在执行list::push_back()
时迭代器不会失效。
所有这些都是vector<>::reserve()
存在的原因,并且为新元素保留了内存是vector<>
将原始内存放置new
的原因。