零初始化自动变量和动态变量规则的区别
the difference of automatic and dynamic variables rules in zero initialization
这样的代码,
#include <iostream>
class obj
{
public:
int v;
};
int main(int argc, char *argv[])
{
obj o1;
std::cout << o1.v << std::endl; // print 32766, indeterminate values
obj *o2 = new obj();
std::cout << o2->v << std::endl; // print 0,but why?
int v1;
std::cout << v1 << std::endl; // print 22024, indeterminate values
int *v2 = new int;
std::cout << *v2 << std::endl; // print 0,but why?
return 0;
}
我知道全局或静态变量将初始化为零。
并自动执行不确定的值。
但是堆对象使用了new关键字,有没有参考解释一下?
obj *o2 = new obj();
是 值初始化 意味着对象将被零初始化,因此数据成员 v
将被初始化为 0
。
这个可以从value initialization看出:
This is the initialization performed when an object is constructed with an empty initializer.
new T () (2)
2,6) when an object with dynamic storage duration is created by a new-expression with the initializer consisting of an empty pair of parentheses or braces (since C++11);
另一方面,
int *v2 = new int; //this uses default initialization
std::cout << *v2 << std::endl; //this is undefined behavior
以上会导致未定义的行为,因为您取消引用v2
并且分配的int
对象未初始化,因此具有不确定的值。
未定义的行为意味着任何事情都可能发生。但是从不依赖(或根据)具有 UB 的程序的输出。程序可能会崩溃。
这个可以从default initialization看出:
This is the initialization performed when an object is constructed with no initializer.
new T (2)
when an object with dynamic storage duration is created by a new-expression with no initializer;
The effects of default initialization are:
- otherwise, no initialization is performed: the objects with automatic storage duration (and their subobjects) contain indeterminate values.
来自 C++ 17 标准(11.6 初始化程序)
11 An object whose initializer is an empty set of parentheses, i.e.,
(), shall be value-initialized.
对于像 int 这样的基本类型,它意味着 zero-initialization。
所以在这个声明中
obj *o2 = new obj();
动态分配对象的数据成员v
是zero-initialized。
至于这段代码
int *v2 = new int;
std::cout << *v2 << std::endl; // print 0,but why?
那么指针v2
指向的对象没有初始化,下一个输出语句可以输出新对象分配的内存区中存储的任何值。
初始化规则是一团乱七八糟的记忆。因此,让我们绕过他们并强制解决这个问题:
class obj
{
public:
int v{};
};
那里,现在 v
总是要初始化的。如果您添加一个不初始化 v
的构造函数,这甚至会起作用,因为编译器会自动添加成员初始化。
至于您的代码为何如此运行:
obj o1;
std::cout << o1.v << std::endl; // print 32766, indeterminate values
o1
是在堆栈(或实际上是寄存器)上创建的,default initialized。其中 int
意味着没有初始化。无论堆栈上(或寄存器中)的随机数据是什么,您都会得到。
obj *o2 = new obj();
std::cout << o2->v << std::endl; // print 0,but why?
来自 C++ 17 标准(11.6 初始化程序):
11 An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
int
的 Value initialization 将其设置为 0。
int v1;
std::cout << v1 << std::endl; // print 22024, indeterminate values
默认初始化,你得到随机数据。
int *v2 = new int;
std::cout << *v2 << std::endl; // print 0,but why?
默认初始化,你得到随机数据。新分配的内存恰好为 0,除非它被应用程序重用。
这样的代码,
#include <iostream>
class obj
{
public:
int v;
};
int main(int argc, char *argv[])
{
obj o1;
std::cout << o1.v << std::endl; // print 32766, indeterminate values
obj *o2 = new obj();
std::cout << o2->v << std::endl; // print 0,but why?
int v1;
std::cout << v1 << std::endl; // print 22024, indeterminate values
int *v2 = new int;
std::cout << *v2 << std::endl; // print 0,but why?
return 0;
}
我知道全局或静态变量将初始化为零。
并自动执行不确定的值。
但是堆对象使用了new关键字,有没有参考解释一下?
obj *o2 = new obj();
是 值初始化 意味着对象将被零初始化,因此数据成员 v
将被初始化为 0
。
这个可以从value initialization看出:
This is the initialization performed when an object is constructed with an empty initializer.
new T () (2)
2,6) when an object with dynamic storage duration is created by a new-expression with the initializer consisting of an empty pair of parentheses or braces (since C++11);
另一方面,
int *v2 = new int; //this uses default initialization
std::cout << *v2 << std::endl; //this is undefined behavior
以上会导致未定义的行为,因为您取消引用v2
并且分配的int
对象未初始化,因此具有不确定的值。
未定义的行为意味着任何事情都可能发生。但是从不依赖(或根据)具有 UB 的程序的输出。程序可能会崩溃。
这个可以从default initialization看出:
This is the initialization performed when an object is constructed with no initializer.
new T (2)
when an object with dynamic storage duration is created by a new-expression with no initializer;
The effects of default initialization are:
- otherwise, no initialization is performed: the objects with automatic storage duration (and their subobjects) contain indeterminate values.
来自 C++ 17 标准(11.6 初始化程序)
11 An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
对于像 int 这样的基本类型,它意味着 zero-initialization。
所以在这个声明中
obj *o2 = new obj();
动态分配对象的数据成员v
是zero-initialized。
至于这段代码
int *v2 = new int;
std::cout << *v2 << std::endl; // print 0,but why?
那么指针v2
指向的对象没有初始化,下一个输出语句可以输出新对象分配的内存区中存储的任何值。
初始化规则是一团乱七八糟的记忆。因此,让我们绕过他们并强制解决这个问题:
class obj
{
public:
int v{};
};
那里,现在 v
总是要初始化的。如果您添加一个不初始化 v
的构造函数,这甚至会起作用,因为编译器会自动添加成员初始化。
至于您的代码为何如此运行:
obj o1;
std::cout << o1.v << std::endl; // print 32766, indeterminate values
o1
是在堆栈(或实际上是寄存器)上创建的,default initialized。其中 int
意味着没有初始化。无论堆栈上(或寄存器中)的随机数据是什么,您都会得到。
obj *o2 = new obj();
std::cout << o2->v << std::endl; // print 0,but why?
来自 C++ 17 标准(11.6 初始化程序):
11 An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
int
的 Value initialization 将其设置为 0。
int v1;
std::cout << v1 << std::endl; // print 22024, indeterminate values
默认初始化,你得到随机数据。
int *v2 = new int;
std::cout << *v2 << std::endl; // print 0,but why?
默认初始化,你得到随机数据。新分配的内存恰好为 0,除非它被应用程序重用。