在构造函数中零初始化数组数据成员
Zero-initializing an array data member in a constructor
我有一个类对象数组,在类对象中我有另一个数组,我需要将其初始化为全零。代码编译并运行,但我的输出显示的是C而不是0.
从头文件:
class Cache {
private:
int byte[16];
public:
Cache();
int getBytes(int);
~Cache();
};
从cpp文件
Cache::Cache()
{
byte[16]={0};
}
int Cache::getBytes(int j){
return byte[j];
}
从另一个CPP文件
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++) //visual check of initializes main memory
{
cout << cache[i].getBytes(j) << " ";
}
}
设置正确吗?如前所述,getBytes返回'C'而不是'0'。
只需在构造函数初始化列表中使用值初始化。这是c++中惯用的方法。
Cache::Cache() : byte()
{
}
注意c++ 11也允许这种语法:
Cache::Cache() : byte{}
{
}
如果你想知道为什么可以工作,从c++ 11标准(注意这也适用于c++ 03):
c++ 11§8.5,
初始化式为圆括号的空集合的对象,即(),应value-initialized。
术语value-initialized带我们到:
c++ 11§8.5,
对T类型的对象进行值初始化意味着:
如果T是一个(可能是cv限定的)类类型9具有用户提供的构造函数(12.1),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是病态的);
如果T是一个(可能是cv限定的)非联合类类型,没有用户提供的构造函数,则对象为零初始化,如果T的隐式声明的默认构造函数是非平凡的,则调用该构造函数。
如果T是数组类型,则每个元素都进行值初始化;
,否则为零初始化
第三个选项触发每个元素的值初始化;第四个应用于每个元素,因为它们(a)没有类类型,所以(1)和(2)没有了,(b)不是数组,所以(3)没有了。这样就只剩下最后一个元素,并且元素都是零初始化的。
在Cache
构造函数中,当您这样做时:
byte[16]={0};
你只设置了数组的第16个字节(这是越界的,所以这个操作有未定义的行为)。数组对象在c++中是默认初始化的,因为您存储int
,所以不执行初始化。
你可以使用std::fill
来初始化它:
Cache::Cache()
{
std::fill(byte, byte+16, 0);
}
你在很多层面上都做错了。您使用的语法并不像您想象的那样。您现在所做的实际上是将表的第17个元素初始化为0。
在您的情况下,memset
可能是最快和最简单的。但是,它不适用于复杂类型,因此我会考虑为一般情况编写一个简单的代码片段,例如:
template<typename T>
inline void zero_init(T array[], size_t elements){
if( std::is_pod<T>() ) memset(array, 0, sizeof(T)*elements);
else std::fill(begin(array), begin(array)+elements, 0);
}
这将检查类型是否为pod类型,这在上下文中意味着它可以通过memset
初始化,并将整个表的0
初始化。如果T
不支持,则对每个元素调用一个等价的element = 0
。此外,检查也可能在编译时进行评估,因此最有可能的是if
将被编译掉,并且在编译时为每种类型创建一个简单的"单行"版本。
你可以通过:
Cache::Cache()
{
zero_init(byte, 16);
}
你的代码有两个问题:
byte[16]={0};
Array有基于0
的索引,所以在这种情况下最大索引可以是15
,而不是16
。你正在破坏内存。
其次,必须遍历所有元素并初始化它们。你的初始化方式将只针对一个元素。
Cache::Cache()
{
for(int i=0;i<16;i++)
byte[i]=0;
}
memset是最简单的解决方案。
Cache::Cache()
{
memset(byte, 0, sizeof(byte));
}
c++ 11支持这种语法:
#include <iostream>
using namespace std;
class Test
{
private:
int bytes[16] = {};
public:
void print()
{
for(int i = 0; i < 16; i++)
{
cout << bytes[i] << " ";
}
cout << endl;
}
};
int main()
{
Test test;
test.print();
}
基本上使用零初始化和默认成员初始化器(默认构造函数)
- C++:__aligned(__alignof__) 导致字符数组数据出现问题?
- 很好的语法来获取对向量/数组数据的大小引用?
- 为什么我无法访问指向数组中成员函数的指针?
- 如何将结构/联合数组的成员传递到函数中
- 使用带有参数包的数组的成员数组初始化类
- 有没有办法给数组的成员指定不同的名称?
- 数组数据以错误的方式遍历 Python/Matlab
- 访问 Arduino 中的结构数组数据
- 在能够从 Web 浏览器访问大型数组数据的同时存储它的最可行方法是什么?
- 使用包含结构的数组的成员函数
- 在C 类中声明数组数据
- C++:释放动态数组(结构成员)和指向此结构的指针的方法
- C 用数组作为成员创建对象
- 将包含数组数据成员的结构保存到文件
- 多维数组数据成员的运行时错误
- C++在初始化类时设置数组数据成员的大小
- 声明的数组数据成员没有大小
- 通过Boost.Python向Python公开C样式数组数据成员
- 是否有一种简单的方法来初始化c++中的动态数组数据成员?
- 在构造函数中零初始化数组数据成员