代码之家  ›  专栏  ›  技术社区  ›  Sumant

C++标准列表和默认可构造类型

  •  0
  • Sumant  · 技术社区  · 16 年前

    为什么它是 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序列容器的接口更加一致。

    6 回复  |  直到 16 年前
        1
  •  5
  •   Peter    16 年前

    std::list没有容量函数,因为它没有任何意义;它从不需要像向量那样调整大小。它的容量只受可用内存的限制,这是不容易确定的。

    根据您的要求,我认为您实际上需要reserve()。这对矢量来说是一次性的,因为它(非常)需要这样的东西;没有特别的要求使所有的函数在所有STL容器中保持一致,特别是当它们对其他容器没有意义时。

    您可以使用自定义分配器来实现相同的效果。正如曼纽尔建议的,看看Boost。

        2
  •  4
  •   anon    16 年前

    没有一般要求类型是默认可构造的-它必须是可复制和可分配的。您的代码不起作用,因为您试图创建一个包含10个项的列表-它们必须以某种方式构造,因此必须使用默认的构造函数-但仅在这种特定情况下。如果您创建了一个空列表并将其添加到其中,那么就没有这样的要求。

    其他容器也是如此-请尝试编译以下内容:

    #include <vector>
    
    struct A {
        A( int x ) : z(x) {}
        int z;
    };
    
    std::vector <A> a(10);
    

    关于您问题的第二部分,我只是观察到接口的一致性不是标准容器的主要设计标准——例如,没有意图将一种类型的容器替换为另一种类型的容器。在斯科特·迈耶斯的《有效的STL》一书的第1和第2项中有一个很好的讨论。

        3
  •  3
  •   Community CDub    8 年前

    Neil already answered the main question .

    另外请注意,调用Resize()时需要一个默认的构造函数。

    你可以通过有一个指向对象的STL指针列表来绕过这个问题,但我想这对你来说已经很明显了。

    在相关的注释中,为什么不 列表中的容量函数?你可以 认为这样的功能会有回报 内存分配成本 以后当你 向后推物体。至少会的 制作两个STL的接口 对容器排序稍微多一些 一致的。

    我想这里的问题是 STL lists allow cross-list splicing . 如果要预先分配内存,请查看 Boost Pool Allocator .

        4
  •  2
  •   Benoît photo_tom    16 年前

    原因是,当您构造一个n个元素的列表(其中n是您在构造函数中使用的参数)时,该列表用t()的副本填充其n个元素的结构。

    sgi stl documentation for list .

        5
  •  0
  •   bayda    16 年前

    为什么只有一个参数 std::list的构造函数需要t 要成为默认的可构造类型吗?

    因为这个构造器-用元素(作为参数传递的数字)创建列表。每个元素的值将是默认值。此外,还可以使用带有两个参数的构造函数来创建带有将用第二个元素值初始化的元素的列表。

    在相关的注释中,为什么不 列表中的容量函数?

    它没有意义,因为向列表中添加新元素的成本比向量的成本要低得多。

    std::vector没有这样的 限制。我的问题是为什么不 使用相同的技术 (创建/销毁习语) std::也列出?

    这不是限制。因为如果不使用此类构造函数,则不需要默认的初始值设定项。向量也是这样。

        6
  •  0
  •   Michael Burr    16 年前

    所以你的问题是“为什么不在列表中列出储备和容量功能?”

    答案是没有理由提前为列表保留内存-添加新元素从不需要为现有元素重新分配和复制,也不要求保存列表内容的内存是连续的,迭代器在执行 list::push_back() .

    所有这些都是 vector<>::reserve() 为新元素保留内存是 vector<> 将执行放置 new 到原始内存中。