没有合适的资源?快使用搜索试试~ 我知道了~
首页C++软件工程师面试最全总结
资源详情
资源评论
资源推荐

I. C++
引用和指针的区别?
指针是一个实体,需要分配内存空间。引用只是变量的别名,不需要分配内存空间。
引用在定义的时候必须进行初始化,并且不能够改变。指针在定义的时候不一定要初始化,并
且指向的空间可变。(注:不能有引用的值不能为 )
有多级指针,但是没有多级引用,只能有一级引用。
指针和引用的自增运算结果不一样。(指针是指向下一个空间,引用时引用的变量值加 )
引用得到的是所指向的变量(对象)的大小,而 指针得到的是指针本身的大小。
引用访问一个变量是直接访问,而指针访问一个变量是间接访问。
使用指针前最好做类型检查,防止野指针的出现;
引用底层是通过指针实现的;
作为参数时也不同,传指针的实质是传值,传递的值是指针的地址;传引用的实质是传地址,
传递的是变量的地址。
从汇编层去解释一下引用
1. 9: int x = 1;
2. 00401048 mov dword ptr [ebp-4],1
3. 10: int &b = x;
4. 0040104F lea eax,[ebp-4]
5. 00401052 mov dword ptr [ebp-8],eax
的地址为 , 的地址为 ,因为栈内的变量内存是从高往低进行分配的。所以
的地址比 的低。 这条语句将 的地址 放入 寄存器 !
"#$"%$这条语句将 的值放入 的地址 中上面两条汇编的作用
即:将 的地址存入变量 中,这不和将某个变量的地址存入指针变量是一样的吗?所以从
汇编层次来看,的确引用是通过指针来实现的。
&''中的指针参数传递和引用参数传递
指针参数传递本质上是值传递,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作
为被调函数的局部变量处理,会在栈中开辟内存空间以存放由主调函数传递进来的实参值,从而形
成了实参的一个副本(替身)。值传递的特点是,被调函数对形式参数的任何操作都是作为局部变
量进行的,不会影响主调函数的实参变量的值(形参指针变了,实参指针不会变)。
引用参数传递过程中,被调函数的形式参数也作为局部变量在栈中开辟了内存空间,但是这时存放
的是由主调函数放进来的实参变量的地址。被调函数对形参(本体)的任何操作都被处理成间接寻

址,即通过栈中存放的地址访问主调函数中的实参变量(根据别名找到主调函数中的本体)。因此,
被调函数对形参的任何操作都会影响主调函数中的实参变量。
引用传递和指针传递是不同的,虽然他们都是在被调函数栈空间上的一个局部变量,但是任何对于
引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量。而对于指针传递的参
数,如果改变被调函数中的指针地址,它将应用不到主调函数的相关变量。如果想通过指针参数传
递来改变主调函数中的相关变量(地址),那就得使用指向指针的指针或者指针引用。
从编译的角度来讲,程序在编译时分别将指针和引用添加到符号表上,符号表中记录的是变量名及
变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应
的地址值为引用对象的地址值(与实参名字不同,地址相同)。符号表生成之后就不会再改,因此
指针可以改变其指向的对象(指针变量中的值可以改),而引用对象则不能修改。
形参与实参的区别?
形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。因此,
形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量。
实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它
们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获
得确定值,会产生一个临时变量。
实参和形参在数量上,类型上,顺序上应严格一致, 否则会发生“类型不匹配”的错误。
函数调用中发生的数据传送是单向的。 即只能把实参的值传送给形参,而不能把形参的值反向
地传送给实参。 因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。
当形参和实参不是指针类型时,在该函数运行时,形参和实参是不同的变量,他们在内存中位于
不同的位置,形参将实参的内容复制一份,在该函数运行结束的时候形参被释放,而实参内容不
会改变。
值传递:有一个形参向函数所属的栈拷贝数据的过程,如果值传递的对象是类对象 或是大的结构
体对象,将耗费一定的时间和空间。(传值)
指针传递:同样有一个形参向函数所属的栈拷贝数据的过程,但拷贝的数据是一个固定为 字节
的地址。(传值,传递的是地址值)
引用传递:同样有上述的数据拷贝过程,但其是针对地址的,相当于为该数据所在的地址起了一
个别名。(传地址)
效率上讲,指针传递和引用传递比值传递效率高。一般主张使用引用传递,代码逻辑上更加紧凑、
清晰。
%%( 的用法和作用?
先来介绍它的第一条也是最重要的一条:隐藏。(%%( 函数,%%( 变量均可)
当同时编译多个文件时,所有未加 %%( 前缀的全局变量和函数都具有全局可见性。
%%( 的第二个作用是保持变量内容的持久。(%%( 变量中的记忆功能和全局生存期)存储在静
态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在
静态存储区:全局变量和 %%( 变量,只不过和全局变量比起来,%%( 可以控制变量的可见范围,
说到底 %%( 还是用来隐藏的。
%%( 的第三个作用是默认初始化为 )(%%( 变量)
其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字
节默认值都是 ))),某些时候这一特点可以减少程序员的工作量。

%%( 的第四个作用:&''中的类成员声明 %%(
函数体内 %%( 变量的作用范围为该函数体,不同于 *% 变量,该变量的内存只被分配一次,
因此其值在下次调用时仍维持上次的值;
在模块内的 %%( 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
在模块内的 %%( 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明
它的模块内;
在类中的 %%( 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
在类中的 %%( 成员函数属于整个类所拥有,这个函数不接收 %+ 指针,因而只能访问类的
%%( 成员变量。
类内:
%%( 类对象必须要在类外进行初始化,%%( 修饰的变量先于对象存在,所以 %%( 修饰的
变量要在类外初始化;
由于 %%( 修饰的类成员属于类,不属于对象,因此 %%( 类成员函数是没有 %+ 指针的,
%+ 指针是指向本对象的指针。正因为没有 %+ 指针,所以 %%( 类成员函数不能访问非
%%( 的类成员,只能访问 %%( 修饰的类成员;
%%( 成员函数不能被 !$%* 修饰,%%( 成员不属于任何对象或实例,所以加上 !$%* 没
有任何实际意义;静态成员函数没有 %+ 指针,虚函数的实现是为每一个对象分配一个 !%$ 指
针,而 !%$ 是通过 %+ 指针调用的,所以不能为 !$%*;虚函数的调用关系,%+,!%$
,(%,!$%**-(%-
静态变量什么时候初始化
初始化只有一次,但是可以多次赋值,在主程序之前,编译器已经为其分配好了内存。
静态局部变量和全局变量一样,数据都存放在全局区域,所以在主程序之前,编译器已经为其
分配好了内存,但在 & 和 &''中静态局部变量的初始化节点又有点不太一样。在 & 中,初始化
发生在代码执行之前,编译阶段分配好内存之后,就会进行初始化,所以我们看到在 & 语言中
无法使用变量对静态局部变量进行初始化,在程序运行结束,变量所处的全局内存会被全部回
收。
而在 &''中,初始化时在执行相关代码时才会进行初始化,主要是由于 &''引入对象后,要
进行初始化必须执行相应构造函数和析构函数,在构造函数或析构函数中经常会需要进行某些
程序中需要进行的特定操作,并非简单地分配内存。所以 &''标准定为全局或静态对象是有首
次用到时才会进行构造,并通过 %%.来管理。在程序结束,按照构造顺序反方向进行逐个
析构。所以在 &''中是可以使用变量对静态局部变量进行初始化的。
(-%/
阻止一个变量被改变,可以使用 (-% 关键字。在定义该 (-% 变量时,通常需要对它进行初
始化,因为以后就没有机会再去改变它了;
对指针来说,可以指定指针本身为 (-%,也可以指定指针所指的数据为 (-%,或二者同时
指定为 (-%;
在一个函数声明中,(-% 可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;

对于类的成员函数,若指定其为 (-% 类型,则表明其是一个常函数,不能修改类的成员变量,
类的常对象只能访问类的常成员函数;
对于类的成员函数,有时候必须指定其返回值为 (-% 类型,以使得其返回值不为“左值”。
(-% 成员函数可以访问非 (-% 对象的非 (-% 数据成员、(-% 数据成员,也可以访问
(-% 对象内的所有数据成员;
非 (-% 成员函数可以访问非 (-% 对象的非 (-% 数据成员、(-% 数据成员,但不可以访
问 (-% 对象的任意数据成员;
一个没有明确声明为 (-% 的成员函数被看作是将要修改对象中数据成员的函数,而且编译器
不允许它为一个 (-% 对象所调用。因此 (-% 对象只能调用 (-% 成员函数。
(-% 类型变量可以通过类型转换符 (-%0(% 将 (-% 类型转换为非 (-% 类型;
) (-% 类型变量必须定义的时候进行初始化,因此也导致如果类的成员变量有 (-% 类型的变
量,那么该变量必须在类的初始化列表中进行初始化;
对于函数值传递的情况,因为参数传递是通过复制实参创建一个临时变量传递进函数的,函数
内只能改变临时变量,但无法改变实参。则这个时候无论加不加 (-% 对实参不会产生任何影
响。但是在引用或指针传递函数调用中,因为传进去的是一个引用或指针,这样函数内部可以
改变引用或指针所指向的变量,这时 (-%才是实实在在地保护了实参所指向的变量。因为在
编译阶段编译器对调用函数的选择是根据实参进行的,所以,只有引用传递和指针传递可以用
是否加 (-% 来重载。一个拥有顶层 (-% 的形参无法和另一个没有顶层 (-% 的形参区分开
来。
(-% 成员函数的理解和应用?
1 (-%2%(342%(355%!.6(-%2%(347(-%
1 处 (-%:确保返回的 2%(3 对象在以后的使用中不能被修改
6 处 (-%:确保此方法不修改传递的参数 2
7 处 (-%:保证此方法不修改调用它的对象,(-% 对象只能调用 (-% 成员函数不能调用
非 (-% 函数
指针和 (-% 的用法
当 (-% 修饰指针时,由于 (-% 的位置不同,它的修饰对象会有所不同。
-%8(-% 中 (-% 修饰 的值所以理解为 的值不可以改变,即 只能指向固定的一
个变量地址,但可以通过8 读写这个变量的值。顶层指针表示指针本身是一个常量
-%(-%8 或者 (-%-%8 两种情况中 (-% 修饰8,所以理解为8 的值不可以改变,
即不可以给8 赋值改变 指向变量的值,但可以通过给 赋值不同的地址改变这个指针指向。
底层指针表示指针所指向的变量是一个常量。
-%(-%8(-%9
) *%
如果需要在 (-% 成员方法中修改一个成员变量的值,那么需要将这个成员变量修饰为
*%。即用 *% 修饰的成员变量不受 (-% 成员方法的限制9
可以认为 *% 的变量是类的辅助状态,但是只是起到类的一些方面表述的功能,修改他的内
容我们可以认为对象的状态本身并没有改变的。实际上由于 (-%0(% 的存在,这个概念很多时
候用处不是很到了。

%$- 用法?
%$- 修饰变量的声明
如果文件 ( 需要引用 ( 中变量 -%!,就可以在 ( 中声明 %$--%!,然后就可以引用变
量 !。
%$- 修饰函数的声明
如果文件 ( 需要引用 ( 中的函数,比如在 ( 中原型是 -%*-.-% *,那么就可以在 (
中声明 %$--%*-(-% *),然后就能使用 *- 来做任何事情。就像变量的声明一样,
%$--%*-(-% *)可以放在 ( 中任何地方,而不一定非要放在 ( 的文件作用域的范围
中。
%$- 修饰符可用于指示 & 或者 &++函数的调用规范。
比如在 &++中调用 & 库函数,就需要在 &++程序中用 %$-:&;声明要引用的函数。这是给
链接器用的,告诉链接器在链接的时候用 & 函数规范来链接。主要原因是 &++和 & 程序编译完
成后在目标代码中命名规则不同。
-% 转字符串字符串转 -%/%$(%%$(<%$-(< % (< 的内部实现?
('' 标准增加了全局函数 %"55%0%$-=
可以使用 %"55%>%>% 等等函数
%$(< 拥有返回值,有时候函数原本不需要返回值,但为了增加灵活性如支持链式表达,
深拷贝与浅拷贝?
浅复制 —只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种
拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中
对象被改变了,那么浅复制出来的对象也会相应改变。
深复制 —在计算机中开辟了一块新的内存地址用于存放复制的对象。
剩余63页未读,继续阅读

















123QIANG
- 粉丝: 2
- 资源: 5
上传资源 快速赚钱
我的内容管理 收起
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助

会员权益专享
安全验证
文档复制为VIP权益,开通VIP直接复制

评论0