C ++ - 未初始化的向量<int> </int>的值

时间:2011-03-07 16:44:08

标签: c++ vector scope initialization

我从this question的答案中理解,global / static uninitialized int的值将为0. this one的答案表示对于向量,将调用对象类型的默认构造函数。

我无法弄清楚 - 当我在本地函数中有vector<int> v(10)时会发生什么。 int 的默认构造函数是什么?如果我在全球范围内声明了vector<int> v(10)该怎么办?

我所看到的是,本地函数中的vector<int> v(10)导致变量为0 - 但我不确定这只是因为我的编译器还是固定的预期行为。

7 个答案:

答案 0 :(得分:39)

它不是未定义的行为,矢量会自动初始化其所有元素。如果需要,您可以选择其他默认值。

构造函数是:

vector( size_type, T t = T() )

并且对于int,默认类型(由int()返回)为0。

在本地函数中:

int x;

不保证将变量初始化为0。

int x = int();

会这样做。

int x();

遗憾的是,两者都没有宣布一个功能。

答案 1 :(得分:38)

零初始化在标准中指定为内置类型的默认零初始化/值初始化,主要是为了在模板使用中仅支持这种类型的情况。

请注意,此行为与int x;等本地变量不同,后者保留未初始化的值(如C语言中继承的行为)。

答案 2 :(得分:9)

您正在使用的构造函数实际上有两个参数,第二个参数是可选的。它的声明如下:

explicit vector(size_type n, const T& value = T())

第一个参数是最初在vector中创建的元素数量;第二个参数是要复制到每个元素中的值。

对于任何对象类型TT()称为“值初始化”。对于数字类型,它会为您提供0。对于具有默认构造函数的类类型,它为您提供了一个使用该构造函数进行默认构造的对象。

有关“魔术括号”的详细信息,我建议阅读Michael Burr对问题"Do the parentheses after the type name make a difference with new?"的优秀答案。它与new具体使用时讨论了值初始化,但大多数情况下是适用于值初始化,无论其他地方都可以使用。

答案 3 :(得分:3)

int的默认值为零。因此vector<int> v(10)将使用零初始化所有10个元素!

int main() {
        std::vector<int> v(10);
        for ( int i = 0 ; i < 10 ; i++ )
           std::cout << v[i] << std::endl;
        return 0;
}

输出:

0
0
0
0
0
0
0
0
0
0

在ideone上运行:http://ideone.com/IbcyH

答案 4 :(得分:1)

int类型的默认初始化是将其初始化为0.

对于大多数(如果不是全部)原始类型都是如此:char将初始化为(char)0(或'\0'如果您愿意),float将初始化为{ {1}},任何指针都初始化为0.0f。对于其他类型,将调用无参数构造函数。

通常,只要您无法指定构造函数(或选择不执行),就会发生默认初始化。

答案 5 :(得分:1)

默认情况下,矢量元素是零初始化的,不是默认初始化的。这是两个不同但相关的概念:

  • 零初始化是对没有显式初始化的静态对象所做的操作,以及对初始化列表中给定的成员执行的操作,初始化为()。对于基本类型,使用的值为0转换为类型。

  • 默认初始化是对未显式初始化的非静态变量和成员所做的操作。对于基本类型,它保持未初始化状态。

(而C ++ 0X引入的值初始化仍然不同)。

答案 6 :(得分:1)

正如其他人提到的,发生的事情是零初始化开始。我实际上在我的代码中使用了很多(向量和其他类之外):

some_type my_var = some_type();

这使我能够确保我的变量始终正确初始化,因为默认情况下 C/C++ 不会初始化基本类型(char、short、int、long、float、double 等)

从 C++11 开始,您也可以在类定义中这样做:

class MyClass
{
...
    int   my_field_ = 123;       // explicit initialization
    int   your_field_ = int();   // zero initialization
};

对于向量,std 库使用 T()。无论 T() 是什么,它都会使用默认的初始化。对于一个类,它调用默认构造函数。对于基本类型,它使用零 ('\0', 0, 0.0f, 0.0, nullptr`)。

正如 James McNellis 和 Nawaz 所提到的,可以将用于初始化向量的值设置为:

std::vector<int> foo(100, 1234);

当您调整矢量大小时,该功能也可用(如果矢量缩小,则忽略默认值):

foo.resize(200, 1234);

这样你就可以有一个默认的初始化值。但是,这很棘手,因为您必须确保所有定义和 resize() 调用都使用该默认值。这就是您想要编写自己的类以确保始终将默认值传递给向量函数的时候。

但是,如果您想有一种方法自动初始化为特定值,您可以通过这种方式混合使用这两种功能:

struct my_value {
    int   v = 123;
};

std::vector<my_value>  foo(100);

// here foo[n].v == 123 for n in [0, 100)

这是我处理这个问题的首选方式(即如果我不希望默认为零)。这是一个额外的 .v,但更不容易出错,并且在创建 my_value 的向量时不需要知道默认值。

另外,对于那些认为这会很慢的人来说,它不会。就 C++ 而言,结构就像语法糖。一个优化后,它将与简单的 std::vector<int> foo(100, 123) 完全相同。