LeetCode C++基础面试题汇总附答案(四)

目录

前言

面试题及答案

1. C++ 中的指针参数传递和引用参数传递

2. 形参与实参的区别?

3. int fun() 和 int fun(void) 的区别?

4. C语言 struct 和 C++ struct 区别

5. const 有什么用途?

6. 什么是类的继承?

7. STL 迭代器如何实现

8. STL 中 list 与 queue 之间的区别?

9. 野指针是什么?如何检测内存泄漏?

10. 如何避免野指针?


前言

 这里整理了leetCode C++的基础面试第四部分,希望对大家有所帮助

面试题及答案

1. C++ 中的指针参数传递和引用参数传递


指针参数传递本质上是值传递,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,会在栈中开辟内存空间以存放由主调函数传递进来的实参值,从而形成了实参的一个副本(替身)。值传递的特点是,被调函数对形式参数的任何操作都是作为局部变量进行的,不会影响主调函数的实参变量的值(形参指针变了,实参指针不会变)。
引用参数传递过程中,被调函数的形式参数也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参(本体)的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量(根据别名找到主调函数中的本体)。因此,被调函数对形参的任何操作都会影响主调函数中的实参变量。
引用传递和指针传递是不同的,虽然他们都是在被调函数栈空间上的一个局部变量,但是任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量。而对于指针传递的参数,如果改变被调函数中的指针地址,它将应用不到主调函数的相关变量。如果想通过指针参数传递来改变主调函数中的相关变量(地址),那就得使用指向指针的指针或者指针引用。
从编译的角度来讲,程序在编译时分别将指针和引用添加到符号表上,符号表中记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值(与实参名字不同,地址相同)。符号表生成之后就不会再改,因此指针可以改变其指向的对象(指针变量中的值可以改),而引用对象则不能修改。


2. 形参与实参的区别?


形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。因此,形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量。
实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值,会产生一个临时变量。
实参和形参在数量上,类型上,顺序上应严格一致, 否则会发生“类型不匹配”的错误。
函数调用中发生的数据传送是单向的。 即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。 因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。
当形参和实参不是指针类型时,在该函数运行时,形参和实参是不同的变量,他们在内存中位于不同的位置,形参将实参的内容复制一份,在该函数运行结束的时候形参被释放,而实参内容不会改变。
值传递:有一个形参向函数所属的栈拷贝数据的过程,如果值传递的对象是类对象 或是大的结构体对象,将耗费一定的时间和空间。(传值)
指针传递:同样有一个形参向函数所属的栈拷贝数据的过程,但拷贝的数据是一个固定为4字节的地址。(传值,传递的是地址值)
引用传递:同样有上述的数据拷贝过程,但其是针对地址的,相当于为该数据所在的地址起了一个别名。(传地址)
效率上讲,指针传递和引用传递比值传递效率高。一般主张使用引用传递,代码逻辑上更加紧凑、清晰。


3. int fun() 和 int fun(void) 的区别?


这里考察的是c 中的默认类型机制。
在c中,int fun() 会解读为返回值为int(即使前面没有int,也是如此,但是在c++中如果没有返回类型将报错),输入类型和个数没有限制, 而int fun(void)则限制输入类型为一个void。 在c++下,这两种情况都会解读为返回int类型,输入void类型。


4. C语言 struct 和 C++ struct 区别


C语言中:struct是用户自定义数据类型(UDT);
C++中struct是抽象数据类型(ADT),支持成员函数的定义,(C++中的struct能继承,能实现多态)。
C中struct是没有权限的设置的,且struct中只能是一些变量的集合体,可以封装数据却不可以隐藏数据,而且成员不可以是函数。
C++中,struct的成员默认访问说明符为public(为了与C兼容),class中的默认访问限定符为private,struct增加了访问权限,且可以和类一样有成员函数。
struct作为类的一种特例是用来自定义数据结构的。一个结构标记声明后,在C中必须在结构标记前加上struct,才能做结构类型名


5. const 有什么用途?


1).定义只读变量,或者常量(只读变量和常量的区别参考下面一条);
2).修饰函数的参数和函数的返回值;
3).修饰函数的定义体,这里的函数为类的成员函数,被const修饰的成员函数代表不能修改成员变量的值


6. 什么是类的继承?


类与类之间的关系
has-A包含关系,用以描述一个类由多个部件类构成,实现has-A关系用类的成员属性表示,即一个类的成员属性是另一个已经定义好的类;
use-A,一个类使用另一个类,通过类之间的成员函数相互联系,定义友元或者通过传递参数的方式来实现;
is-A,继承关系,关系具有传递性;


7. STL 迭代器如何实现


迭代器是一种抽象的设计理念,通过迭代器可以在不了解容器内部原理的情况下遍历容器,除此之外,STL中迭代器一个最重要的作用就是作为容器与STL算法的粘合剂。
迭代器的作用就是提供一个遍历容器内部所有元素的接口,因此迭代器内部必须保存一个与容器相关联的指针,然后重载各种运算操作来遍历,其中最重要的是*运算符与->运算符,以及++、--等可能需要重载的运算符重载。这和C++中的智能指针很像,智能指针也是将一个指针封装,然后通过引用计数或是其他方法完成自动释放内存的功能。
最常用的迭代器的相应型别有五种:value type、difference type、pointer、reference、iterator catagoly;


8. STL 中 list 与 queue 之间的区别?


list不再能够像vector一样以普通指针作为迭代器,因为其节点不保证在存储空间中连续存在;
list插入操作和结合才做都不会造成原有的list迭代器失效;
list不仅是一个双向链表,而且还是一个环状双向链表,所以它只需要一个指针;
list不像vector那样有可能在空间不足时做重新配置、数据移动的操作,所以插入前的所有迭代器在插入操作之后都仍然有效;
deque是一种双向开口的连续线性空间,所谓双向开口,意思是可以在头尾两端分别做元素的插入和删除操作;可以在头尾两端分别做元素的插入和删除操作;
deque和vector最大的差异,一在于deque允许常数时间内对起头端进行元素的插入或移除操作,二在于deque没有所谓容量概念,因为它是动态地以分段连续空间组合而成,随时可以增加一段新的空间并链接起来,deque没有所谓的空间保留功能。


9. 野指针是什么?如何检测内存泄漏?


野指针:指向内存被释放的内存或者没有访问权限的内存的指针。
“野指针”的成因主要有3种:
指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。例如
char *p = NULL;
char *str = new char(100);
指针p被free或者delete之后,没有置为NULL;
指针操作超越了变量的作用范围。


10. 如何避免野指针?


对指针进行初始化
①将指针初始化为NULL。
char * p = NULL;
②用malloc分配内存
char * p = (char * )malloc(sizeof(char));
③用已有合法的可访问的内存地址对指针初始化
char num[ 30] = {0};
char *p = num;
指针用完后释放内存,将指针赋NULL。
delete(p);
p = NULL;

上一篇:LeetCode C++基础面试题汇总附答案(三)

参考:
链接:https://leetcode.cn/leetbook/read/da-han-hou-duan-gang-ti-mu-he-ji-shang/nixycc/
 

猜你喜欢

转载自blog.csdn.net/lejian/article/details/129160989