某一天突然被问到一个问题:
怎么我的类成员变量在构造函数中明明已经初始化为零了,所有赋值的地方都断点了,也没有断点到被修改,怎么用它做判定条件的时候又有值了,而且有时候有,有时候正常
于是,讲解一下类中成员变量的空间部署:
一个类对象的地址就是类所包含的这一片内存空间的首地址,这个首地址也就对应具体某一个成员变量的地址。类的内存大小和其唯一的成员变量的内存大小是一致的(这个就是结构体一样的,类中有函数而已,但是类中的函数都是放在代码区,不影响其大小)
有了这个概念再来看一段代码
#include <iostream>
using namespace std;
int main()
{
struct MyStruct
{
int num1[10];
int sex;
};
MyStruct My;
memset(&My, 0, sizeof(My));
int num2[11] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2 };
memcpy(My.num1, num2, sizeof(num2));
cout << My.sex << endl;
system("pause");
return true;
}
!!!用结构体代替类了,从上面可以看出,定义的结构体My,
其大小 sizeof(My) = 44
定义的num2 = 44
所以将num2的大小拷贝到结构体My中,就会出现下图所示情况,没有给变量sex赋值,但是最后打印出来的值已经被改变。
第二种情况、数组下标越界
很多情况,喜欢使用数组(数组小,下标方便)
int A[10] = {0};
void setAValue(int index,int t)
{
A[index]=t;
}
setAValue(1,100);
setAValue(111,111);
如上图所示,就会出现数组下标越界问题。做好下标范围判断很有必要
三、拷贝越界(strncpy,memcpy等拷贝)
char A[32];
std::string Name = "";
//第一种,直接拷贝
strncpy(A,Name.c_str(),Name.size());
//这种情况会出现当Name长度很长的时候,赋值越界
所以我们在拷贝的时候,首先就是要考虑拷贝的内容和大小
#define LEN_NICKNAME 32
char A[LEN_NICKNAME];
std::string Name = "";
//第一种,直接拷贝
strncpy(A,Name.c_str(),Name.size());
//第二种判断长度后拷贝
if (Name.size() > LEN_NICKNAME - 1)
{
auto str = Name[i].substr(0, LEN_NICKNAME - 1) + '\0';
strncpy(A, str.c_str(), LEN_NICKNAME );
}
else
{
strncpy(A, Name.c_str(), Name.size());
}
使用 strncpy 等安全函数时,当复制字符串到达指定的长度时,不会在目标字符串结尾添加 '\0' 字符,必须手工进行添加 '\0' 字符。当然,可以在申请内存时,将最后一个字节置为 '\0' 字符;也可以在调用 strncpy 函数后,紧接着赋 '\0' 字符。
暂时就是出现这么几个内存问题,后续遇到其他的问题再补充。