C++ 零初始化
C++ Zero-Initialization
我无法理解 class 中的某个成员何时以及为何根据 http://en.cppreference.com/w/cpp/language/zero_initialization 被零初始化。
考虑以下测试程序:
#include <iostream>
#include <stdio.h>
class MyTest {
private:
const static unsigned int dimension = 8;
void (* myFunctions [dimension])();
public:
MyTest() {}
void print() {
for(unsigned int i=0; i < MyTest::dimension; i++) {
printf("myFunctions[%d] = %p\n", i, this->myFunctions[i]);
}
}
};
int main() {
//We declare and initialize an object on the stack
MyTest testObj = {};
testObj.print();
return 0;
}
我正在声明一个 class 以具有签名 "void functionname()" 的 8 个函数指针数组。当我将 main
中的 class 的对象声明并初始化为 MyTest testObj = {};
或 MyTest testObj;
时,我希望它被零初始化,即所有指针都是空指针。
然而,在我的 Windows 10 机器和 g++ -m32 -o test -std=c++14 test.cpp && test
机器上用 g++ 5.3.0 编译给出输出:
myFunctions[0] = 76dd6b7d
myFunctions[1] = 00401950
myFunctions[2] = 0061ff94
myFunctions[3] = 004019ab
myFunctions[4] = 00401950
myFunctions[5] = 00000000
myFunctions[6] = 003cf000
myFunctions[7] = 00400080
这看起来像是堆栈中未初始化的值..
如果我将对象的声明移到 main 之外(作为全局变量),它会再次打印全零。
如果我没有正确理解 cppreference,那是因为我有一个具有静态存储持续时间的变量,因此被零初始化。它通过零初始化我的 class(即 myFunctions
)数组的所有非静态数据成员来初始化我的 class 类型。一个数组是通过对它的每个元素进行零初始化来初始化的,在我的函数指针的情况下,它是一个空指针。
当我用 MyTest testObj = {};
声明对象时,为什么它不对堆栈进行零初始化?
以下
MyTest testObj = {};
不是 MyTest
的零初始化,而是简单地调用其默认构造函数。 cppreference 页面解释了原因(强调我的):
As part of value-initialization sequence for non-class types and for members of value-initialized class types that have no constructors, including value initialization of elements of aggregates for which no initializers are provided.
MyTest
是一个class类型,a有一个构造函数。
用
定义构造函数
MyTest() = default;
将改为零初始化对象。
下面的相关标准引述(强调我的)。
来自[dcl.init#8]:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type with either no default constructor ([class.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
...
List-initialization of an object or reference of type T is defined as follows:
...
Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
我无法理解 class 中的某个成员何时以及为何根据 http://en.cppreference.com/w/cpp/language/zero_initialization 被零初始化。
考虑以下测试程序:
#include <iostream>
#include <stdio.h>
class MyTest {
private:
const static unsigned int dimension = 8;
void (* myFunctions [dimension])();
public:
MyTest() {}
void print() {
for(unsigned int i=0; i < MyTest::dimension; i++) {
printf("myFunctions[%d] = %p\n", i, this->myFunctions[i]);
}
}
};
int main() {
//We declare and initialize an object on the stack
MyTest testObj = {};
testObj.print();
return 0;
}
我正在声明一个 class 以具有签名 "void functionname()" 的 8 个函数指针数组。当我将 main
中的 class 的对象声明并初始化为 MyTest testObj = {};
或 MyTest testObj;
时,我希望它被零初始化,即所有指针都是空指针。
然而,在我的 Windows 10 机器和 g++ -m32 -o test -std=c++14 test.cpp && test
机器上用 g++ 5.3.0 编译给出输出:
myFunctions[0] = 76dd6b7d
myFunctions[1] = 00401950
myFunctions[2] = 0061ff94
myFunctions[3] = 004019ab
myFunctions[4] = 00401950
myFunctions[5] = 00000000
myFunctions[6] = 003cf000
myFunctions[7] = 00400080
这看起来像是堆栈中未初始化的值..
如果我将对象的声明移到 main 之外(作为全局变量),它会再次打印全零。
如果我没有正确理解 cppreference,那是因为我有一个具有静态存储持续时间的变量,因此被零初始化。它通过零初始化我的 class(即 myFunctions
)数组的所有非静态数据成员来初始化我的 class 类型。一个数组是通过对它的每个元素进行零初始化来初始化的,在我的函数指针的情况下,它是一个空指针。
当我用 MyTest testObj = {};
声明对象时,为什么它不对堆栈进行零初始化?
以下
MyTest testObj = {};
不是 MyTest
的零初始化,而是简单地调用其默认构造函数。 cppreference 页面解释了原因(强调我的):
As part of value-initialization sequence for non-class types and for members of value-initialized class types that have no constructors, including value initialization of elements of aggregates for which no initializers are provided.
MyTest
是一个class类型,a有一个构造函数。
用
定义构造函数MyTest() = default;
将改为零初始化对象。
下面的相关标准引述(强调我的)。
来自[dcl.init#8]:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type with either no default constructor ([class.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
...
List-initialization of an object or reference of type T is defined as follows:
...
Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.