【问题标题】:vector and primitive type initialisation向量和原始类型初始化
【发布时间】:2014-10-03 08:14:42
【问题描述】:

我了解到,例如,如果您在全局范围内声明一个 int,

int x; //默认为0;

在本地范围内,

void f() {
    int x; //undefined
}

但是,如果我们在全局或局部范围内使用向量:

向量 v(3); //使用 int 的默认构造函数将 v 初始化为 {0,0,0}。

我们可以通过这样做在本地范围内默认初始化 int 类向量的元素:

int x = int(); //默认为0

我认为如果我们使用 int 的默认构造函数,它会分配在堆中。

  1. 为什么不能像 T x; 那样在本地范围内默认初始化原始类型?或者
  2. 在本地范围内,为什么向量(不知道其他容器)使用元素的默认构造函数,而不是像 int 声明一样让它们未初始化?
  3. 当前方法对这两种类型有什么好处?为什么它们以不同的方式初始化?这与性能有关吗?

【问题讨论】:

  • 1) 因为这是语言指定它的方式。 2) 因为这就是 C+ 标准所说的 std::vector 应该如何工作。
  • 如果调用 int 构造函数,它将不会在堆上分配。仅当您使用 new 关键字时。您可以使用int x();int x = int()

标签: c++ vector


【解决方案1】:

出于“性能”的原因,之所以这样,是因为 C++ 人希望 1980 年代的 C 人没有任何理由抱怨“为我们不需要的东西买单”。这是 C++ 的原则之一,不为不使用的东西支付(运行时)成本。因此,旧式 POD 类型默认情况下是未初始化的,尽管具有构造函数的类和结构总是会调用其中一个构造函数。

如果我今天指定它,我会说本地范围内的 int x; 将被默认初始化(为 0),如果您想避免这种情况,您可以说类似 int x = std::noinit; 的内容。现在这样做已经太晚了,但实际上我已经在某些课程类型中做到了,因为性能很重要:

class SuperFast
{
  struct no_init_t {};
public:
  no_init_t no_init;
  SuperFast() : x(0), y(0) {}
  SuperFast(no_init_t) {}

private:
  int x, y;
};

这样,默认构造会给出一个有效的对象,但如果你有严重的理由需要避免这种情况,你可以。如果你知道你很快就会覆盖一大堆这些对象,你可能会使用这种技术——不需要默认构造它们:

SuperFast sf(SuperFast::no_init); // look ma, I saved two nanoseconds!

【讨论】:

  • 如果有构造函数的类调用它们的默认构造函数,那不是已经违反了这个不为你不使用的东西支付运行时成本吗?
  • @recursivePointer:好问题。不,因为想要“no-init”行为的类可以实现一个允许它的特殊构造函数。我将编辑我的答案来证明这一点。
  • 所以换句话说,旧的 POD 类型默认是未初始化的,主要是因为 c 兼容性,并且库中具有构造函数的类不能声明为未初始化。对吗?
  • 差不多——标准库的人没有为他们的类型提供“noinit”构造函数,可能是因为它不是正确的 OOP。 :) 但有时为了获得最高性能,您必须违反封装、不变量等。我意识到这有点自相矛盾,但欢迎使用 C++!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-05
  • 2011-05-18
  • 1970-01-01
相关资源
最近更新 更多