开发工具:
文件大小: 4mb
下载次数: 0
上传时间: 2019-07-16
详细说明:该资料包含c++基础,操作系统,数据结构,算法,设计模式,数据库模块4.形参与实参的区别?
1)形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存
单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使
用该形参变量。
2)实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数
调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋
值,输入等办法使实参获得确定值,会产生一个临时变量
3)实参和形参在数量上,类型上,顺序上应严格一致,否则会发生“类型不匹配”的
错误
4)函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参,而不能把形
参的值反向地传送给实参。因此在函数调用过程中,形参的值发生改变,而实参中
的值不会变化
5)当形参和实参不是指针类型时,在该函数运行时,形参和实参是不同的变量,他们
在内存中位于不同的位置,形参将实参的内容复制一份,在该函数运行结束的时候
形参被释放,而实参內容不会改变
1)值传递:有一个形参向函数所属的栈拷贝数据的过程,如果值传递的对象是类对象
或是大的结构体对象,将耗费一定的时间和空间。(传值)
2)指针传递:同样有一个形参向函数所属的栈拷贝数据的过程,但拷贝的数据是一个
固定为4字节的地址。(传值,传递的是地址值)
3)引用传递:同样有上述的数据拷贝过程,但其是针对地址的,相当于为该数据所在
的地址起了一个别名。(传地址)
4)效率上讲,指针传递和引用传递比值传递效率髙。一般主张使用引用传递,代码逻
辑上更加紧凑、清晰。
5.!!! static的用法和作用?
1.先来介绍它的第一条也是最重要的一条:隐藏。( static函数, static变量均可)
当同时编译多个文件时,加 static前缀的全局变量和函数都只在当前文件中可见。
2. static的第二个作用是保持变量内容的持久。( static变量中的记忆功能和全局生
存期)存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一
次初始化。共有两种变量存储在静态存储区:全局变量和 static变量,只不过和全局
变量比起来, static可以控制变量的可见范围,说到底 static还是用来隐藏的。
3. static的第三个作用是默认初始化为0( static变量)
其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,
内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。
!4. static的第四个作用:C++中的类成员声明 static
1)函数体内 static变量的作用范围为该函数体,不同于auto变量,该变量的内存
只被分配一次,因此其值在下次调用时仍维持上次的值;
2)在模块内的 static全局变量可以被模块内所用函数访问,但不能被模块外其它函
数访问;
3在模块内的 static函数只可被这一模块內的其它函数调用,这个凶数的使用范围
被限制在声明它的模块内
4)在类中的 static成员变量属于整个类所拥有,对类的所有对象只有一份拷
贝
5)在类中的 static成员函数属于整个类所拥有,这个函数不接收this指针,因而
只能访问类的 static成员变量
6) static类对象必须要在类外进行初始化, static修饰的变量先于对象存在,所以
static修饰的变量要在类外初始化;
7)由于 static修饰的类成员属于类,不属于对象,因此 static类成员函数是没有t
his指针的,this指针是指向本对象的指针。正因为没有this指针,所以 static
类成员函数不能访问非 static的类成员,只能访问 static修饰的类成员;
8) static成员函数不能被 virtual修饰, static成员不属于任何对象或实例,所以
加上 virtual没有任何实际意义;静态成员函数没有this指针,虚函数的实现是
为每一个对象分配一个vptr指针,而vptr是通过this指针调用的,所以不能为
virtual;虚函数的调用关系,this>vptr> ctable >virtual function
6.静态变量什么时候初始化
1)初始化只有一次,但是可以多次赋值,在主程序之前,编译器已经为其分配好了內
存
2)静态局部变量和全局变量样,数据都存放在全局区域,所以在主程序之前,编译
器已经为其分配好了内存,但在C和C+中静态局部变量的初始化节点又有点不太
一样。在C中,初始化发生在代码执行之前,编译阶段分配好内存之后,就公进行
初始化,所以我们看到在C语言中无法使用变量对静态局部变量进行初始化,在程
序运行结束,变量所处的全局内存会被全部回收
3)而在C+中,初始化时在执行相关代码时才会进行初始化,主要是由于C++引入对
象后,要进行初始化必须执行相应构造函数和析构函数,在构造函数或析构函数中
经常会需要进行某些程序中需要进行的特定操作,并非简单地分配内存。所以C++
标准定为全局或静态对象是有首次用到时才会进行构造,并通过 atexit来管理。
在程序结束,按照构造顺序反方问向进行逐个析构。所以在C+中是可以使用变量对
静态局部变量进行初始化的。
7.!!! const?
1)阻止一个变量被改变,可以使用 cons t关键字。在定义该 const变量时,通常需要
对它进行初始化,因为以后就没有机会再去改变它了
2)对指针来说,顶层 const,指针本身不能被改变,底层 const,指针指向的值不能被
变
3)在一个函数声明中, const可以修饰形参,表明它是一个输入参数,在函数内部不
能改变其值
4)对于类的成员函数,若指定其为 cons t类型,则表明其是一个常函数,不能修改类
的成员变量,类的常对象只能访问类的常成员函数
5)对于类的成员函数,有时候必须指定其返回值为 const类型,以使得其返回值不为
“左值”
6) cous t成员函数可以访问非 cons t对象的非 cons t数据成员、 cons t数据成员,也
可以访问 const对象内的所有数据成员;
7)非 cons t成员函数可以访问非 const对象的非 const数据成员、 const数据成员,
但不可以访问 const对象的任意数据成员
8)一个没有明确声明为 const的成员函数做看作是将要修改对象中数据成员的函数,
而且编译器不允许它为一个 cons t对象所调用。因此 cons t对象只能调用 cons t成
员函数。
9) const类型变量可以通过类型转换符 const cast将 const类型转换为非 const类
型
10) cons t类型变量必须定义的时侯进行初始化,因此也导致如果类的成员变量有 const
类型的变量,那么该变量必须在类的初始化列衣中进行初始化
11)对于函数值传递的情况,因为参数传递是通过复制实参创建一个临时变量传递进
数的,函数内只能改变临时变量,但无法改变实参。则这个时候无论加不加 const
对实参不会产生任何影响。但是在引用或指针传递函数调用中,因为传进去的是
个引用或指针,这样函数内部可以改变引用或指针所指向的变量,这时 const才是
实实在在地保护了实参所指向的变量。因为在编译阶段编译器对调用函数的选择是
根据实参进行的,所以,只有引用传递和指针传递可以用是否加 const来重载。
个拥有顶层 const的形参无法和另一个没有顶层 const的形参区分开米
8.!!! const成员函数的理解和应用
① const stock& Stock: topal(② const stock&s)③ const
①处 const:确保返回的 Stock对象在以后的使用中不能被修改
②处 const:确保此方法不修改传递的参数S
③处 const:保证此方法不修改调用它的对象(this), const对象只能调用cons
t成员函数,不能调用非 cons t函数
9.!指针和 const的用法
1)当 const修饰指针时,由于 cons t的位置不同,它的修饰对象会有所不同
2)顶层 cons t,int米 const p2,表示指针本身是个常量
3)底层 const, int const*p1或者 const int*p1,表示指针所指向的变量是一个常
量
4) int cons tκ const p,指针木身和指向的变量均不能被改变;
10. mutable
1)如果需要在 const成员方法中修改一个成员变量的,那么需要将这个成员变量修饰
为 mutable。即用 mutable修饰的成员变量不受 cons t成员方法的限制
2)可以认为 mutable的变量是类的辅助状态,但是只是起到类的一些方面表述的功能,
修改他的内容我们可以认为对象的状态本身并没有改变的。实际上由于 const cast
的存在,这个概念很多时候用处不是很到了
11. extern用法?
1) extern修饰变量的声明
如果文件a.c需要引用b.c中变量intv,就可以在a.c中声明 extern int v,然后
就可以引用变量v
2) extern修饰函数的声明
如果文件a.c需要引用b.c中的函数,比如在b.c中原型是 int fun( int mu),那么
就可以在a.c中声明 extern int fun(intm),然后就能使用fun来做任何事
情。就像变量的声明·样, extern int fun( int mu)可以放在a.c中任何地方,
而不一定非要放在a.c的文件作用域的范围中。
3) extern修饰符可用于指示C或者C++函数的调用规范
比如在C++中调用C库函数,就需要在C++程序中用 extern“C”声明要引用的
函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原
因是C十十和C程序编译完成后在目标代码中命名规则不同
12.int转字符串,字符串转int? strcat, strcpy, strncpy, memset, memcpy
的内部实现?
c+11标准增加了全局函数std:: to string--int转字符串
可以使用std:atoi/atol/ato1l等等函数-字符串转int
strcpy拥有返回值,有时候函数原本不需要返回值,但为了增加灵活性如支持链式表达
13.!深拷贝与浅拷贝?
1)浅复制—只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引
用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被
复制的内存地址,如果原地址中对象被改变了,那么浅复制出米的对象也会相应改
变
深复制一在计算机中开辟了一块新的内存地址用于存放复制的对象
Student sl
内存
Student/s2(s1)
1次构造,两次析
name
指针
构,内存泄漏
s1和s2中包含的指针对象同时指向一块内
存,析构时 delete了两次这个内存块就出错
深拷贝
Student s1
内存1
Student s2(s1)
内存2
内造52时拷贝一块和s1指向数据块一样大的数据块,并将
直拷贝下来,这样s1和s2指向各自的效据块,析构时辉放
各自的数据块
综上所述,浅共贝是只刈针过行贝,两个者指向同一个内存块,深拷贝是刈指针和针指向的内容都进行贝
川后的指针是指向不同闪的指针。
2)在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对
象里的值完全复制给另一个对象,如A-B。这时,如果B中有一个成员变量指针已
经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B
把內存释放了(如:析构),这A内的指针就是野指针了,出现运行错误。
14.!!C++模板是什么,底层怎么实现的?
1)编译器并不是把函数模板处理成能够处理任意类的函数;编译器从函数模板通过具
体类型产生不同的函数;编译器会对函数模板进行两次编译:在声明的地方对模板
代码本身进行编译,生成简陋的函数模板原形,在调用的地方对参数替换后的代码
进行编译,生成具体的函数原形
2)这是因为函数模板要被实例化后才能成为真正的函数,在使用函数模板的源文件中
包含函数模板的头文件,如果该头文件中只有声明,没有定义,那编译器无法实例
化该模板,最终导致链接错误。
15.C语言 struct和C++ struct区别
1)C语言中: struct是用户自定义数据类型(UDT);C++中 struct是抽象数据类型
(ADT),支持成员函数的定义,类似于 class,可以实现继承和多态。
2)C中 struct是没有权限的设置的,c++中的 struct可以设置访问权限,其默认为
public,是对c中 struc t的扩展。
3)C中必须在结构标记前加上 struct,才能做结构类型名,而c++中不需要
16.虚函数可以声明为 inline吗?
1)虚函数用于实现运行时的多态,或者称为晚绑定或动态绑定。而内联函数用于提高
效率。内联函数的原理是,在编译期间,对调用内联函数的地方的代码替换成函数
代码。内联函数对于程序中需要频繁使用和调用的小函数非常有用。
)虚函数要求在运行时进行类型确定,用于实现多态,而内敛函数要求在编译期完成
相关的函数膂换,所以不能声明为内敛函数;
17.!!内联函数优缺点?
1优点
内联函数的原理是,在编译期间,对调用内联函数的地方的代码替换成函数代码。内联函数
对于程序中需要频繁使用和调用的小函数非常有用。可以减少函数调用的开销。
缺点
增加函数体积,不方便调试, debug模式下编译器一般不內联
注意
Inline只是一个內联请求,编译器有权利拒绝,主要有以下几种情况会拒绝:虚调用,函数
体积过大,有递归等。
orceinline关键字可强制内联,主要是函数体积过大时可强制使用,其他情况下仍然不会内联
18.类成员初始化方式?构造函数的执行顺序?为什么用成员初始
化列表会快一些?
1)赋值初始化,通过在函数体内进行赋值初始化;列表初始化,在冒号后使用初始化
列表进行初始化
这两种方式的主要区别在于
对于在函数体中初始化,是在所有的数据成员被分配内存空间后才进行的
列表初始化是给数据成员分配内存空间时就进行初始化,就是说分配一个数据成员
只要冒号后有此数据成员的赋值表达式(此表达式必须是括号赋值表达式),那么分
配了內存空间后在进入函数体之前给数据成员赋值,就是说初始化这个数据成员
此时函数体还未执行。
2)一个派生类构造函数的执行顺序如下
①虚拟基类的构造函数(多个虚拟基类则按照继承的顺序执行构造函数)
②基类的构造函数(多个普通基类也按照继承的顺序执行构造函数)
③类类型的成员对象的构造函数(按照初始化顺序)
④派生类自己的构造函数
3)方法一是在构造函数当中做赋值的操作,而方法是做纯粹的初始化操作。我们
都知道,C艹的娬值操作是会产生临时对象的。临时对象的出现会降低程序的效
19.!!!成员列表初始化?
1)必须使用成员初始化的四种情况
①当初始化一个引用成员时;
②当初始化个常量成员吋,因为引用和 const对象只能初始化不能赋值,构造
函数的体内只能做赋值而不是初始化,所以引用和 const对象只能通过列表初始
化
③如果是继承关系,派生类必须在其初始化列表中调用基类的构造函数
④如果含有类成员,需要在其初始化列表中调用成员类的构造函数
)成员初始化列表做了什么
①编译器会一一操作初始化列表,以适当的顺序在构造函数之前安插初始化操
作,并且在任何显示用户代码之前
②1ist中的项目顺序是由类中的成员声明顺序决定的,不是由初始化列表的顺
序决定的
20.构造函数为什么不能为虚函数?析构函数为什么要虚函数?
1.从存储空间角度,虚函数相应一个指向 vtable虚函数表的指针,这大家都知道
但是这个指向 vtable的指针事实上是存储在对象的内存空间的。问题出来了,假设构
造函数是虚的,就须要通过 vtable来调用,但是对象还没有实例化,也就是内存空间
还没有,怎么找 vtable呢?所以构造函数不能是虚函数。
2.从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到相应的调
用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函
数没有必要是虚函数。虚函数的作用在于通过父类的指针或者引用来调用它的时候可
以变成调用子类的那个成员函数。而构造函数是在创建对象时自己主动调用的,不可
能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数
3.构造函数不须要是虚函数,也不同意是虚函数,由于创建一个对象时我们总是要明
白指定对象的类型,虽然我们可能遥过实验室的基类的指针或引用去訪问它但析构却
不一定,我们往往通过基类的指针来销毁对象。这时候假设析构函数不是虚函数,就
不能正确识别对象类型从而不能正确调用析构函数。
4.从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数从实
际含义上看,在调用构造函数时还不能确定对象的真实类型(由于」类会调父类的构
造函数);并且构造函数的作用是提供初始化,在对象生命期仅仅运行一次,不是对
象的动态行为,也没有必要成为虚函数
5.当一个构造函数被调用时,它做的首要的事情之中的一个是初始化它的WPTR。因
此,它仅仅能知道它是“当前”类的,而全然忽视这个对象后面是否还有继承者。当
编译器为这个构造函数产生代码时,它是为这个类的构造函数产生代码一一既不是为
基类,也不是为它的派生类(由于类不知道谁继承它)。所以它使用的VPTR必须是对
于这个类的 VTABLE。并且,仪仪要它是最后的构造函数调用,那么在这个对象的生命
期内,VPTR将侏持被初始化为指向这个Ⅵ TABLE,但假设接着另一个史晚派生的构造函
数被调用,这个构造函数又将设置VPTR指向它的 VTABLE,等.直到最后的构造函数结
束。vPTR的状态是由被最后调用的构造函数确定的。这就是为什么构造函数调用是从
基类到更加派生类顺序的还有一个理由。可是,当这一系列构造函数调用正发生时,
每个构造函数都已经设置WPIR指向它自己的 VTABLE。假设函数调用使用虚机制,它
将仅仅产生通过它自己的Ⅵ TABLE的调用,而不是最后的ⅥABLE(全部构造函数被调用
后才会有最后的 VTABLE)。
因为构造函数木来就是为了明确初始化对象成员才产生的,然而 virtual
function主要是为了再不完全了解细节的情况下也能正确处理对象。另外, virtual
(系统自动生成,下载前可以参看下载内容)
下载文件列表
相关说明
- 本站资源为会员上传分享交流与学习,如有侵犯您的权益,请联系我们删除.
- 本站是交换下载平台,提供交流渠道,下载内容来自于网络,除下载问题外,其它问题请自行百度。
- 本站已设置防盗链,请勿用迅雷、QQ旋风等多线程下载软件下载资源,下载后用WinRAR最新版进行解压.
- 如果您发现内容无法下载,请稍后再次尝试;或者到消费记录里找到下载记录反馈给我们.
- 下载后发现下载的内容跟说明不相乎,请到消费记录里找到下载记录反馈给我们,经确认后退回积分.
- 如下载前有疑问,可以通过点击"提供者"的名字,查看对方的联系方式,联系对方咨询.