1.什么是虚函数?什么是纯虚函数?
- 虚函数:被`virtual`关键字修饰的成员函数,用于实现多态性,通过基类访问派生类的函数。
- 纯虚函数:在虚函数后面添加`=0`,只有声明而没有实现,需要派生类提供实现。
2.基类为什么需要虚析构函数?
虚析构函数是为了解决父类指针指向子类对象时,释放子类对象的资源时,释放不完全,造成的内存泄漏问题。
3.如何初始化const和static数据成员?
初始化const
在构造函数初始化列表中初始化
在声明时直接初始化
初始化 static
成员:
在类定义之外初始化
在声明时直接初始化
4.指针和引用的区别
-
定义:
-
指针是一个变量,其值为另一个变量的内存地址。
-
引用是一个别名,它是一个已存在变量的别名。
-
-
语法:
-
指针使用
*
来声明指针变量和访问指针所指向的值。 -
引用使用
&
来声明引用,但在使用时不需要使用&
。
-
-
空值:
-
指针可以指向空值(nullptr)。
-
引用必须在定义时初始化,且不允许指向空值。
-
-
重新赋值:
-
指针可以在程序运行时重新指向不同的变量。
-
引用在初始化后不可改变指向的变量。
-
-
运算符重载:
-
指针可以进行运算,如指针加减操作。
-
引用不支持运算符重载。
-
-
传递参数:
-
指针作为参数传递时,传递的是地址,对参数的修改会影响原变量。
-
引用作为参数传递时,传递的是原变量的别名,对参数的修改也会影响原变量。
-
5.new和malloc的区别
new
和 malloc
都是用于在内存中动态分配空间的方法,但在C++中,它们有一些重要的区别。
-
new
是C++中的运算符,而malloc
是C语言中的函数。因此,new
提供了更多的功能和类型安全性。 -
使用
new
分配内存时,不需要指定要分配的内存大小,因为它会根据所需的类型自动计算大小。而malloc
需要显式指定要分配的内存大小。 -
new
返回的是所分配类型的指针,而malloc
返回的是void
类型的指针,需要进行类型转换。 -
new
会调用对象的构造函数,而malloc
不会。这意味着使用new
分配的内存可以自动初始化为默认值,而使用malloc
分配的内存则需要手动初始化。
6.内存泄漏怎么产生的?如何避免?
内存泄漏是指程序在动态分配内存后,由于某种原因未释放已分配的内存,导致系统无法再次使用这部分内存。内存泄漏通常发生在程序中频繁动态分配内存的情况下,如果程序没有正确释放已分配的内存,就会导致内存泄漏。
内存泄漏的产生原因可能包括以下几点:
1,指针重新赋值
2,错误的内存释放
3,返回值的不正确处理
为了避免内存泄漏,可以采取以下几种方法:
确保没有在访问空指针。
每个内存分配函数都应该有一个 free 函数与之对应,alloca 函数除外。
每次分配内存之后都应该及时进行初始化,可以结合 memset 函数进行初始化,calloc 函数除外。
每当向指针写入值时,都要确保对可用字节数和所写入的字节数进行交叉核对。
在对指针赋值前,一定要确保没有内存位置会变为孤立的。
每当释放结构化的元素(而该元素又包含指向动态分配的内存位置的指针)时,都应先遍历子内存位置并从那里开始释放,然后再遍历回父节点。
始终正确处理返回动态分配的内存引用的函数返回值。
7.C++的内存分区
在C++中,内存分区是指程序运行时内存空间的划分。C++程序在运行时会将内存划分为几个不同的区域,主要包括以下几个部分:
-
栈(Stack):栈用于存储函数的参数值、局部变量的值等。每当调用一个函数时,函数的参数值和局部变量会被存储在栈内存中,函数执行完毕后这些数据会被自动释放。
-
堆(Heap):堆用于动态分配内存,程序员可以在堆上手动分配和释放内存。在堆上分配的内存需要程序员手动释放,否则会导致内存泄漏。
-
全局/静态存储区(Global/Static Storage):全局变量和静态变量存储在这个区域。全局变量在程序整个运行周期内都存在,而静态变量在程序执行过程中始终存在,直到程序结束。
-
常量存储区(Constant Storage):存储常量变量,如字符串常量等。这些数据在程序运行期间不可修改。
-
代码区(Code):存储程序的代码,包括函数的机器码等。这部分内存通常是只读的,不允许进行写操作。