为什么支撑初始化分配分配填充垃圾变量
Why does brace initialization assignment fill variables with garbage?
我已经陷入了这样的信念,即使用Brace初始化时会为变量分配其默认值。但是我错了。
在以下示例中:
#include <string>
#include <iostream>
#include <stdint.h>
class A
{
public:
A() {}
~A(){}
int var1;
int32_t var2;
int64_t var3;
std::string var4;
double var5;
float var6;
std::string info() const {
return "var1=" + std::to_string(var1) + " " +
"var2=" + std::to_string(var2) + " " +
"var3=" + std::to_string(var3) + " " +
"var4=" + var4 + " " +
"var5=" + std::to_string(var5) + " " +
"var6=" + std::to_string(var6) + " " +
"n"
;
}
};
int main()
{
A a;
std::cout << "Before assigning variables: " << a.info();
a.var1 = 1;
a.var2 = 2;
a.var3 = 3;
a.var4 = "4";
a.var5 = 5;
a.var6 = 6;
std::cout << "After assigning variables: " << a.info();
a = {};
std::cout << "After brace init assignment: " << a.info();
}
这是结果:
Before assigning variables: var1=0 var2=0 var3=4198240 var4= var5=0.000000 var6=0.000000
After assigning variables: var1=1 var2=2 var3=3 var4=4 var5=5.000000 var6=6.000000
After brace init assignment: var1=2114725200 var2=32766 var3=4199416 var4= var5=0.000000 var6=0.000000
修复它:
- 如果我摆脱了默认的构造函数 - 问题消失了。
如果一个类的成员变量是支撑限制的,则将分配0或默认值。例如:
class A { public: A() {} ~A(){} int var1{}; int32_t var2{}; int64_t var3{}; std::string var4{}; double var5{}; float var6{}; };
有人可以解释为什么会发生这种情况吗?我在这里缺少什么?
a = {};
是一个分配,a
是从{}
构造的临时对象分配的。隐式生成的分配将对所有数据成员执行成员的分配,那么关键是如何从{}
初始化临时对象。
这是副本列表限制,因为效果,进行了价值定位。
否则,如果支撑式列表为空,而T是具有默认构造函数的类类型,则进行Value-Initialization。
作为价值定性的影响,
1(如果t是没有默认构造函数的类类型或用户提供或删除的默认构造函数,则该对象是默认的initialized;
A
具有用户提供的默认构造函数,并且作为默认初始化的效果,该默认构造函数用于初始化临时对象。用户提供的默认构造器的主体为空的,对于临时对象,var4
将通过std::string
的默认构造函数默认initialial,所有其他具有Build-In类型类型的数据成员都将具有不确定的值。
- 如果我摆脱了默认构造函数 - 问题消失了。
然后,价值定位的行为将变为
(强调我的(
2(如果t是具有默认构造函数的类类型,该类型既不提供用户提供也不删除(也就是说,它可能是具有隐式定义或默认默认型构建器的类对象为零initialized ,然后如果它具有非平凡的默认构造函数,则将其默认限制化;
请注意,此处的差异,临时对象首先将被零定位。然后,所有具有建筑类型的数据成员都将初始化为0
(var4
仍被默认initialized(。
- 如果类的成员变量是支撑式化的,则将其分配给0或默认值。
这是默认初始化器列表的工作方式。
通过默认成员初始化器,这仅是成员声明中包含的支撑或等于初始化器,如果在成员初始化器列表中省略了会员
中使用该成员。
然后所有数据成员都是由指定的初始化器初始化的;在您的示例中,它们都是价值限制的,因为效果var4
被默认为initialized,其他成员对0
进行了零命名。
a = {};
此行并不意味着类内的所有变量都获得{} initializer。相反,它调用(未定义,因此自动生成(副本(或移动(分配操作员,该操作员从用{}(即具有非注重变量(创建的对象进行浅复制/移动到您拥有的对象。
var4 似乎要清除,但实际上是从新对象var4复制/移动的,并且由于std :: string具有默认的构造函数,因此是空的。<<<<<<<<<<<<<<<<
避免类似内容的简单解决方案是初始化班级中的非类变量,例如
class A
{
int var = 0;
...
};
- 何时在函数中声明堆栈分配变量?
- 取消引用指针并立即为其分配变量,导致分段错误
- 在C++中动态分配变量类型
- 在函数 (c++) 中分配变量类型和大小数组
- 无法在命名空间范围内分配变量
- 自我分配变量的定义
- 在 CUDA C++中分配变量 - 无法分配设备变量
- 在 CPP 中动态分配变量的数据类型
- 为什么无法在类主体中分配变量?
- const 类方法是否阻止在类外部分配变量?
- 从文件中分配变量,并使用定界符分配
- 分配指针后,是否可以为指针指向的事物分配变量名称?
- 读取外部文件并在类似xml的输入中分配变量
- 有没有办法在不分配变量的情况下将字符串连接到数字
- 如果使用alloca在内联函数中的堆栈上分配变量,那么在内联函数返回后,其引用是否有效
- 堆分配变量的结构成员对齐
- 包含溢出缓冲区的堆栈分配变量,也称为缓冲区
- 在 GetTransfer 之后,我在帐户 1 收到未分配变量错误。我无法弄清楚我搞砸了什么逻辑错误
- 对动态分配的变量的引用与指向相同动态分配变量的指针
- 在C++中为用户输入分配变量