结构中的默认值和构造函数顺序
default value in struct and the constructor order
我知道我们可以为结构成员设置默认值。例如,我可以为这些成员设置默认值:
struct Foo {
int a = 0;
int b = 1;
int c;
}
假设我有另一个成员 c:
的构造函数
struct Foo {
int a = 0;
int b = 1;
int c;
foo(int input_c): c(input_c) {}
}
在这种情况下,当我构造一个Foo时,构造顺序是什么?如果我这样做
Foo(100)
我的理解是a和b都是先默认构造然后c赋值100,对吗?
------------更新--------------------
我的部分困惑也是执行顺序。对于默认值,是否已经在构造函数之前执行了?
例如,我可以改变我的 Foo
struct Foo {
int a = 0;
int b = 1;
int c = -1;
foo(int d) {
c += d; // Does c always started with -1?
}
}
是的,成员将按照它们在 class 中声明的顺序进行初始化。
所以当你调用Foo(100)
时,a
和b
会被初始化为默认值,然后c
会被初始化为100
.
初始化的顺序非常严格,总是声明成员的顺序。
首先,应用所有默认的 in-class 初始化程序(按照成员声明的顺序),除非被初始化列表否决。
然后使用构造函数初始化列表,其中列出的任何成员都按照它们声明的顺序进行初始化。如果这些列出的成员中的任何一个也有 in-class 初始值设定项,那么这些不会发生并且初始化列表获胜并用于初始化成员。
然后执行构造函数体。此时所有成员都已经初始化,通过 in-class 初始化或初始化列表。但是构造函数主体可以选择 为那些已初始化的成员分配 新值。
在任何情况下,对于给定的成员 foo
它将由 in class 初始化(如果有)或初始化列表(如果有)初始化,或者默认初始化.无论使用何种方法对其进行初始化,初始化总是发生在它之前声明的另一个成员之后和之后声明的另一个成员之前。
例如:
struct s {
int a = 1;
int b = 42;
int c = 666;
int d;
int e;
s() : e(3), b(123) {
c = 7;
}
};
上面总是首先初始化 a
并且因为它有一个 in-class 初始化器,所以将被使用。它的值将是 1
.
b
第二个初始化。它有一个 in-class 初始化器,但构造函数初始化列表否决了它。它将被初始化为值 123
.
然后c
被初始化为值666
。
d
未初始化/或者更确切地说;默认初始化,对于 int
与未初始化相同,但对于其他类型,如 std::string
意味着初始化为空字符串 - 这取决于类型是否具有可用值。
然后e
被初始化为值3
。这是最后发生的,因为它是最后声明的。它在构造函数的初始化列表中列出的顺序无关紧要。
然后执行构造函数体,c
被赋值为7
。所以它既被初始化又被分配给——这通常是低效的。
对象构造现已完成。
我知道我们可以为结构成员设置默认值。例如,我可以为这些成员设置默认值:
struct Foo {
int a = 0;
int b = 1;
int c;
}
假设我有另一个成员 c:
的构造函数struct Foo {
int a = 0;
int b = 1;
int c;
foo(int input_c): c(input_c) {}
}
在这种情况下,当我构造一个Foo时,构造顺序是什么?如果我这样做
Foo(100)
我的理解是a和b都是先默认构造然后c赋值100,对吗?
------------更新--------------------
我的部分困惑也是执行顺序。对于默认值,是否已经在构造函数之前执行了?
例如,我可以改变我的 Foo
struct Foo {
int a = 0;
int b = 1;
int c = -1;
foo(int d) {
c += d; // Does c always started with -1?
}
}
是的,成员将按照它们在 class 中声明的顺序进行初始化。
所以当你调用Foo(100)
时,a
和b
会被初始化为默认值,然后c
会被初始化为100
.
初始化的顺序非常严格,总是声明成员的顺序。
首先,应用所有默认的 in-class 初始化程序(按照成员声明的顺序),除非被初始化列表否决。
然后使用构造函数初始化列表,其中列出的任何成员都按照它们声明的顺序进行初始化。如果这些列出的成员中的任何一个也有 in-class 初始值设定项,那么这些不会发生并且初始化列表获胜并用于初始化成员。
然后执行构造函数体。此时所有成员都已经初始化,通过 in-class 初始化或初始化列表。但是构造函数主体可以选择 为那些已初始化的成员分配 新值。
在任何情况下,对于给定的成员 foo
它将由 in class 初始化(如果有)或初始化列表(如果有)初始化,或者默认初始化.无论使用何种方法对其进行初始化,初始化总是发生在它之前声明的另一个成员之后和之后声明的另一个成员之前。
例如:
struct s {
int a = 1;
int b = 42;
int c = 666;
int d;
int e;
s() : e(3), b(123) {
c = 7;
}
};
上面总是首先初始化 a
并且因为它有一个 in-class 初始化器,所以将被使用。它的值将是 1
.
b
第二个初始化。它有一个 in-class 初始化器,但构造函数初始化列表否决了它。它将被初始化为值 123
.
然后c
被初始化为值666
。
d
未初始化/或者更确切地说;默认初始化,对于 int
与未初始化相同,但对于其他类型,如 std::string
意味着初始化为空字符串 - 这取决于类型是否具有可用值。
然后e
被初始化为值3
。这是最后发生的,因为它是最后声明的。它在构造函数的初始化列表中列出的顺序无关紧要。
然后执行构造函数体,c
被赋值为7
。所以它既被初始化又被分配给——这通常是低效的。
对象构造现已完成。