面试题:一个类不含指针,也不含虚函数,是否可以使用memset?

旅行   2024-09-27 11:56   广东  

欢迎关注本公众号,专注面试题拆解

分享一套视频课程:《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来清零类对象的内存:

#include <iostream>#include <cstring> // 包含 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;}
在这个例子中,memset只是填充了SimpleClass对象的内存,它不会影响this指针,因为this指针不是类的成员之一。
跳出面向对象的思想去看this
C++在汇编层面,没有对象这种东西,只有函数和各种地址、数据。一个类可以有多个对象(实例),但函数只有一份,所以实际上不是对象拥有了一个函数,而是函数被告知操作一个对象。
在 C++ 中,类是一种抽象的数据类型,它包含数据成员(即属性)和成员函数(即方法)。当创建一个类的对象时,实际上是分配了一块内存来存储该类的数据成员。成员函数则是独立存在的函数,它们通过 this 指针来访问当前对象的数据成员。this是在函数调用栈中提供的,运行期间需要访问对象,此时的this指向就这个对象,编译器将其替换为这个对象的地址,那么这个函数就知道我要操作这个地址了,也就是操作这个对象。
在汇编代码级别,成员函数看起来就像是普通的函数,只是它们接受了一个额外的参数 this,这个参数指向当前对象的地址。例如:
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 指针指向的地址
; 调用 myMethodcall myMethod

在这个例子中,myMethod函数接受一个额外的参数this,这个参数指向 MyClass对象的地址。通过这个指针,函数可以访问和修改对象的数据成员。

对象与函数的关系:一个类可以有多个对象,但成员函数在内存中只有一份。每次调用成员函数时,通过this指针来确定当前操作的对象。

总结:

this 指针的位置:this 指针不是类的一部分,它是由编译器在成员函数调用期间隐式提供的。

内存布局:类对象的内存布局只包含类声明的成员变量,this 指针不占据这部分内存。

memset 的使用:使用memset来初始化或清零这种类对象的内存是安全的,因为memset只是填充类对象的内存,不会影响this指针。

构造函数初始化:对于只包含基本类型的类,使用memset来初始化成员通常是安全的,但构造函数初始化仍然是更好的选择。

end



CppPlayer 



关注,回复【电子书】珍藏CPP电子书资料赠送

精彩文章合集

专题推荐

【专辑】计算机网络真题拆解
【专辑】大厂最新真题
【专辑】C/C++面试真题拆解

CppPlayer
一个专注面试题拆解的公众号
 最新文章