记录一下平时遇到的c++ 的一些基础知识
1
1. C++中的“引用”和“指针”有什么区别?
首先指针是指向内存中的某一块区域,引用是引用的是地址的名字,而且指针是有数据类型的,
- 引用必须在创建时初始化,并且不能重新赋值给其他对象,它就像是对象的另外一个名字。
- 指针是一个变量,它存储了另外一个变量的内存地址。指针可以在任何时候改变指向的对象
2. 解释C++中的构造函数和析构函数。
构造函数是我们调用类的实例就会执行, 而析构函数是类执行完毕调用的
- 构造函数 : 用来创建对象时初始化对象的成员变量
- 析构函数: 它在对象生命周期结束时调用,用于清理工作,比如释放资源
3. 什么是C++中的虚函数,它如何实现多态?
虚函数就是在基类声明(virtual),在派生类重写的函数(override),可以使用基类的指针或者引用来调用派生类的虚函数
实现多态主要是靠的是虚函数来进行实现
4. 描述C++中的重载和重写的区别。
- 重载发生在同一个类中,指的是有多个同名的函数,但是他们传入的参数类型或数量不相同
- 重写发生在继承关系的类中间 ,就比如前面的虚函数的重写
5. 如何在C++中防止一个类被继承?
- 在c++ 中, 可以讲类声明为**final(**c++ 11 之后) 这样类就不能继承了
6. 什么是C++标准模板库(STL)?
- c++ 标准模板库是指类的集合,它提供了常用的数据结构 比如向量 ,列表 队列 和 一些算法: 排序 搜索等等
8. 解释C++中的运算符重载。
- 运算符重载允许给现有的c++运算符赋予自定义的的含义,从而让用于用自定义类型以直观的方式使用运算符
9. 什么是C++中的纯虚函数?
- 纯虚函数是指在基类中声明但不定义的虚函数, 它必须在派生类中进行实现, 一个包含纯虚函数的类被称为抽象类,但不能实例化
10. C++11标准引入了哪些新特性?
- C++11增加了许多特性,包括自动类型推导的auto关键字、基于范围的for循环、智能指针、lambda表达式等。
11. 解释C++中的自动存储、静态存储、动态存储和线程存储持续时间。
- 自动存储 :在函数内部声明的变量 , 在函数调用时创建,在函数结束时销毁
- 静态存储: 通过全局变量和静态变量,在程序开始时 创建,在程序结束时销毁
- 动态存储 :通过new 和delete 分配和释放的内存,它的声明周期又程序员控制
- 线程存储: c++ 11 引入,线程局部存储的变量的生命周期与线程的生命周期相同
2
1. 为什么析构函数必须是虚函数
这个主要是存在于基类有被派生类继承的情况 , 假如我有一个基类 base 以及一个继承了基类的派生类 food , 如果说我们的构造函数不是虚函数的话,那么就会出现内存泄漏的问题 , 就比如下面的代码:
base *p = new food() ;
delete p ;
- 此时我们delete的话,就会调用base的析构函数释放资源,但如果base的构造函数不是虚函数的话,如果在food中有动态分配的资源(如内存) ,此时就得不得及时的释放,会导致内存的一系列问题 。
- 但是如果base的构造函数虚函数的话, c++ 动态绑定会确保调用正确的析构函数 。 即便 p 是 base类型的指针 , c++ 允许时也会检查p实际指向的对象的类型,并调用food 的析构函数,从而正确的释放资源
2. 为什么c++ 默认的析构函数不是虚函数
如果我们的类不存在继承关系的话,设置构造函数是会占用我们的内存资源的,这样得不偿失, 因为我们的虚函数需要额外的虚函数和虚表指针的
3.析构函数的作用
如果构造函数打开了一个文件,最后不需要文件时就需要被关闭, 构造函数允许类自动完成类似的清理的工作, 而不需要调用其他函数 。
构造函数是一类特殊的函数,它于构造函数的作用恰恰相反,它用来完成对象被删除前的一些清理工作,也就是专门的扫尾工作 。
3
3.1 说一下 静态变量和 全局变量的区别
静态变量和 全局变量主要的区别在于他们的作用域以及生命周期的不同
- 全局变量 : 全局变量具有全局作用域,可以在程序的任何地方进行访问 , 也可以 在不同的文件也可以进行调用, 生命周期从程序开始时创建 到程序结束时销毁
- -静态变量 :具有局部作用域 , 只能在定义它的局部代码里使用 , 静态变量也是在程序开始时进行创建, 直到程序结束什是销毁,比如定义在函数内部的话就之能在该函数内部使用, 定义在该文件下的就只能在该文件进行使用 。
3.2 描述一下指针和数组的区别
- 指针是一个变量,其存储的值是内存地址。指针可以通过取址操作获得变量的地址,并可以修改指针的值,使其指向不同的内存位置。通过解引用操作,可以访问指针所指向地址上存储的值。指针可以指向任何数据类型,包括基本类型、结构体、函数等
- 数组是一种数据结构,它在内存中连续存储一系列相同类型的元素。数组名代表数组首元素的地址,通过数组名可以访问数组中的元素。数组的大小在定义时确定,并且无法更改。数组在内存中分配一块连续的存储空间,可以通过索引访问数组中的元素。
4. 在c语言中 , 栈上存储的数据类型有那些
- 局部变量 : 局部变量的仅作用于当前的函数 , 当函数调用结束,自动释放栈的空间
- 函数的参数 :当参数被调用时 , 参数的值会被传递到栈相应的位置, 供函数内部使用
- 函数的返回值: 函数的返回值也是存储在栈上 ,当函数执行完毕准备返回时, 返回的值会被存储在栈上相应的位置,返回时被取出
- 函数的 返回地址: 当函数执行时返回地址会被保存到栈上, 当函数执行完毕后能够找到函数的调用点
- 函数调用的上下文: 当函数调用时, 编译器会自动保存一些上下文信息到栈上, 方便函数在执行过程中正确的管理局部的变量和参数等信息
此外除了上述数据, 栈上还存储 了一些临时的变量 , 和编译过程中的中间结果, 栈上存储的数据是临时的,一旦函数执行结束或调用返回,栈上的数据就会被释放, 不再有效 。
5. c语言中, 堆上存储的数据有?
在c语言中, 堆上主要存储的是程序员手动分配的内存区域:
一般主要存储的数据有
- 动态分配的数据: 使用malloc, calloc , realloc 等函数动态分配的内存块,这些函数从堆中分配指定大小的内存块, 并返回指向这些内存的指针
int *array = malloc(10 * sizeof(int)) ;
//分配一个整数数组
- 用户定义的数据结构 :比如结构体(struct) 和类 , 如果他们是使用malloc 或相关函数动态分配的
typedef struct {
int data ;
struct Node *Next ;
}Node ;
Node *node=malloc(sizeof(Node)) ; //动态分配一个结构体
- 动态分配数据: 不同于在栈上创建的固定大小的数据,堆上的数组可以在运行时确定其大小
char *buffer = malloc(100 * siezeof(char)) ;
//动态分配一个字符数组