25

以及如何编写自己的数组类以使其元素不需要默认构造函数?现在,当我执行 new [] 来分配空间时,我需要一个默认构造函数。

std::vector 没有。

他们是如何做到这一点的?

4

4 回答 4

32

std::vector不需要默认构造函数,因为它从不使用它。每次它需要构造一个元素时,它都使用复制构造函数来完成它,因为每次它都有要复制的东西:现有的向量元素或您自己提供的用于通过方法的参数进行复制的元素(显式或隐式,通过依赖在默认参数上)

您可以以完全相同的方式编写这样的类:每次您需要在数组中构造一个新元素时,都要求用户提供一个用于复制的元素。在这种情况下,构建该原始元素成为用户的责任。

每次它看起来好像std::vector“需要”你的默认构造函数时,它只是意味着你在某个地方依赖于某些vectors 方法的默认参数,即是试图默认构造一个元素,而不是向量。同样,向量本身永远不会尝试默认构造元素。

为了避免内存分配期间的默认构造函数要求,标准库分配未初始化的原始内存块,然后立即在该原始内存块中复制构造新元素(这是new[]无法做到的)。此功能被封装在std::allocator类中。您也可以std::allocator在您的代码中使用,这意味着您也可以立即使用“魔法”。

注意:以上适用于 C++ 语言规范的 C++11 之前版本。C++11 改变了很多东西。这些变化确实创造了std::vector可以在内部使用默认构造函数的情况。

同样值得注意的是,即使是最初的 C++98 规范也允许实现使用函数重载而不是默认参数来实现标准库接口。这意味着形式上可以有一个在内部std::vector使用默认构造函数的有效 C++98 实现。

于 2010-03-04T05:13:38.620 回答
11

std::vector仅当您以需要默认构造函数的方式使用元素时,才需要元素具有默认构造函数。因此,此代码(从已删除的答案中窃取)将无法编译,因为X没有默认 ctor:

#include <vector>

struct X
{
  X(int) {}
};

int main(void)
{
  std::vector<X> x(1); // vector of length 1, second argument defaults to X() !!
  return 0;
}

但是如果你main这样写:

int main(void)
{
  std::vector<X> x; // make empty vector
  x.push_back(X(1));
  return 0;
}

然后它工作正常。

于 2010-03-04T05:15:28.527 回答
8

您可以分配一个字节块,然后在将新项目推到向量后面时,通过复制构造函数(当然不是默认构造函数)使用放置new来创建(您的参数类型)的新实例。T这将不允许制作“N 个默认初始化 Ts 的向量”(std::vector 可以制作 - 这就是为什么它确实需要 T 为此目的具有默认构造函数),但您可以制作开始的向量空的,可以让 Ts 推到他们身上。

于 2010-03-04T05:06:31.970 回答
0

对我来说std::vector,我的类需要一个默认构造函数(比如T),因为我正在调用resize()的方法vector,尽管我只是调用该方法来缩小向量,但永远不会增长。

于 2020-06-21T10:00:44.580 回答