欢迎关注本公众号,专注面试题拆解
分享一套视频课程:《C++实现百万并发服务器》 面试需要项目的可以找我获取,免费分享。 欢迎V:fb964919126
一个类不含指针,也不含虚函数,是否可以使用memset?
上一篇文章 面试题:new出来的对象可以使用bzero等函数初始化内部变量为0吗?——信锐技术一面 最后留的思考题。
我们都知道,每个类对象都有一个隐含的this指针,上一篇文章当中提到了类包含指针成员的时候不能用memset,那么只有基本类型的类是否可以使用呢?毕竟它有一个隐含的this指针。
答案是:可以使用memset
原因是什么呢?
this指针并不是类的一部分,它不占用类的任何空间。this 指针是一个特殊的指针,它指向当前对象的起始地址,用于在成员函数内部引用当前对象。(思考下另外一个面试题:空类的大小是多少?是不是1而不是指针大小的4或者8,this指针不会影响sizeof(对象)的结果)
当使用memset 来初始化一个类的实例时,this指针并没有被显式地初始化或改变。memset只是对对象的内存进行填充,它并不会修改this指针的行为或其指向的地址。因此,this指针仍然正确地指向对象的起始地址。
从内存布局上看:类对象的内存布局是连续的,memset 只是对这块连续内存进行填充。类对象的内存中不包含 this 指针,this 指针是在函数调用栈中提供的。
假设有一个简单的类:
class SimpleClass {
public:
int value;
double value2;
float value3;
};
当创建一个SimpleClass的实例时,内存布局如下:
SimpleClass obj;
假设 sizeof(int) 为4字节,sizeof(double)为8字节,sizeof(float)为4字节,那么SimpleClass的大小将是:
sizeof(SimpleClass) = sizeof(int) + sizeof(double) + sizeof(float);
对于大多数现代系统,这将是 4 + 8 + 4 = 16 字节(考虑对齐情况,实际大小可能会有所不同)。
使用memset来清零类对象的内存:
class SimpleClass {
public:
int value;
double value2;
float value3;
};
int main() {
SimpleClass obj;
// 使用 memset 初始化所有成员为 0
std::memset(&obj, 0, sizeof(SimpleClass));
// 检查成员变量的值
std::cout << "value: " << obj.value << std::endl; // 输出 0
std::cout << "value2: " << obj.value2 << std::endl; // 输出 0.0
std::cout << "value3: " << obj.value3 << std::endl; // 输出 0.0
return 0;
}
class MyClass {
public:
void myMethod() {
// 访问成员变量
x = 42;
}
private:
int x;
};
; 假设 MyClass 的大小为 4 字节
MyClass myObject;
; 成员函数 myMethod 的汇编代码
myMethod:
; 参数列表:this 指针
mov eax, [esp + 4] ; 加载 this 指针(假设在栈上的偏移量为 4)
mov [eax], 42 ; 将 42 写入到 this 指针指向的地址
; 调用 myMethod
call myMethod
在这个例子中,myMethod函数接受一个额外的参数this,这个参数指向 MyClass对象的地址。通过这个指针,函数可以访问和修改对象的数据成员。
对象与函数的关系:一个类可以有多个对象,但成员函数在内存中只有一份。每次调用成员函数时,通过this指针来确定当前操作的对象。
总结:
this 指针的位置:this 指针不是类的一部分,它是由编译器在成员函数调用期间隐式提供的。
内存布局:类对象的内存布局只包含类声明的成员变量,this 指针不占据这部分内存。
memset 的使用:使用memset来初始化或清零这种类对象的内存是安全的,因为memset只是填充类对象的内存,不会影响this指针。
构造函数初始化:对于只包含基本类型的类,使用memset来初始化成员通常是安全的,但构造函数初始化仍然是更好的选择。
end
CppPlayer
关注,回复【电子书】珍藏CPP电子书资料赠送
精彩文章合集
专题推荐