关于inline 函数的总结

关于一天一总结:

1.关于C++inline 关键字,以下说法正确的是:D

使用inline  关键字的函数会被编译其器在调用处展开

B  头文件中可以包含inline函数的声明

C.可以在同一个项目的不同源文件内定义函数名相同但是实现不同的inline函数

D.定义在class声明里面的成员函数默认是inline函数

E优先使用class 声明内定义的inline函数

F优先使用class实现的内inline函数的实现

 

A.如果只声明含有inline 关键字,就没有内联的效果,内联函数的定义必须放在头文件中,编译器才能在调用点展开定义,有些函数即使被声明为内联函数的也不一定回被编译器内联:比如说虚函数和递归函数,通常,递归函数不应该声明为内联函数

———————————————————————————————————————

B.内联函数关键字inline只有跟定义放在一起才有效

———————————————————————————————————————

C.inline函数可以定义在源文件中,但是多个源文件中的同名inline函数的实现必须相同

———————————————————————————————————————

D定义在类声明里的函数将自动成为内联函数

E.F中不存在优先级顺序

————————————————————————

关于inline函数的总结(上次写的博客inline 函数是来自《c/c++编程指南》,这次把我所有的资料上关于内联的都总结出来了):

主要是以下几个 问题

1.什么是inline?

答:一个函数的程序进行代码拓展而不被调用,用相应的函数代码替换函数调用。

 

 

2.为什么要用函数内联?

答:为了提高程序执行的效率,内联函数的代码会被直接插入到每个调用函数的地方,从而减少函数的开销

 

 

3.使用宏定义和使用函数内联有什么区别?

答:

宏定义:

1宏定义是通过文本替换来实现的

2不用普通函数调用就看起来像函数调用

3宏的实现使用的是预处理器,直接用宏代码进行调用,所以就没有参数压栈,生成汇编语言,返回参数等时间花费,所有工作由预处理器完成

4但是宏会产生意想不到的边际效应,因为它只进行单纯的文本替换,如果是表达式,展开后的优先级就会跟原来的不一样

5预处理器不允许存取私有数据

6预处理器对参数不会进行安全检查

 

函数内联:

1inline 对编译器来说是一种请求,而不是命令

2)对参数进行类型安全检查

3)可以存取私有数据成员

4)定义在类中的函数自动成为内联函数

5)循环和递归不能为内联函数

 

4.使用函数内联有什么缺点?

(1)任何种类的循环都会被认为太复杂而不被拓展为内联函数

(2)内联只能在定义它的源文件中使用

3内联是以代码的膨胀为代价,对于函数体比较短的函数应该采用内联。但是对于函数体比较长的,内联形式的使用反而会降低效率。

4类的构造函数和析构函数容易让人误解为使用内联更加有效,但是构造函数和析构函数很可能偷偷隐藏一些行为,所以最好把构造函数和析构函数放在类声明的外面

5.内联具体是怎么实现的?

编译器在它的符号表里放入函数类型和参数(包括函数名字和参数类型及返回值类型),另外,编译器看到内联函数和内联函数的分析没有错时,函数的代码也被放入符号表中,代码是以源程序的形式存放还是以编译过的指令存放取决于编译器

调用一个内联函数时,编译器首先保证正确,即所有的参数类型必须是正确的或者编译器能够将类型转换为正确类型,并且返回值在目标表达式里应该是正确的类型或者可以改为正确的类型。

 

假如内联函数是成员函数,对象的地址(this)指针就会被放到合适的位置,这也是预处理器做不到的

6.使用内联有什么要求么?

1短函数,对于函数体较长的函数,内联就会降低效率。

2如果一个函数是在类声明内定义的,它将自动转换为内联函数

3在头文件里,内联函数默认为内部连接---即它是static,并且只能再被包含的编译单元里面看到,因此,只要他们在不相同的编译单元中声明,在内联函数和全局函数之间用相同的名字,在连接时也不会发生冲突

4inline 必须与函数定义体放在一起才能使函数成为内联,inline放在声明前不起任何作用,是一种用于实现的关键字,而不是用于声明的关键字。函数的实现与声明不能混为一谈

————————————————————————————————————————————————————

下面是参考书籍:

Inline函数内联:

c/c++参考大全》

1.c++中,用户可以创建实际上不调用的短函数,它们的代码在每次调用的程序行得到扩展,这个过程类似于使用类函数的宏,为了使一个函数在程序行内进行代码扩展而不被调用,只要在函数前面加上inline关键字即可

Inline 对于编译器来说是一种请求,而不是 命令

在类声明内定义短函数是有可能的,如果一个函数是在类声明内定义的,它将被自动转换为内联函数,没有必要在函数声明之前加上inline 关键字,构造函数和析构函数也可以是内联函数。

———————————————————————————————————————————

c++primer plus

 

常规函数调用使程序跳到另外一个地址:函数地址,并在函数结束时返回

具体实现:执行到函数调用指令时,程序将在函数调用时立即存储该指令的内存地址,并将函数参数复制到堆栈,跳到标记函数起点的内存单元,执行函数代码,然后调回到地址被保存的指令处,来回跳跃并记录位置:普通函数调用时需要一定的开销。

C++中的内联提供了另一种选择,编译器将使用相应的函数代码替换函数调用,对于内联代码,程序无需跳到另一个位置执行代码,然后再跳回来,所以内联函数的运行速度比常规函数快,但是需要占用更多的内存

****如果程序在10个不同的地方调用同一个内联函数,则该程序将包含该函数的10个代码拷贝

内联与宏

宏是通过文本替换来实现的

——————————————————————————————————————————————————————————————————————

 

c++编程思想1

C中,保护效率的一个方法是使用宏,宏可以不用普通函数调用就使之看起来像函数调用,宏的实现使用预处理器而不是编译器,预处理器直接用宏代码进行宏调用,所以就没有了参数压栈,生成汇编语言的CALL,返回参数等时间花费,所有工作都由预处理器完成,

宏的两个问题:

1.预处理器不允许存取私有数据

2.会产生意想不到的边际效应

(1)边际效应:宏代码在展开时只是文本替换,可以通过加()来解决

(2)表达式在宏内展开时,优先级跟原来的优先级就会不一样

如果只将内联关键字inline 与函数声明写到一起,就会被当成普通函数对待

Inline还会对函数参数和返回值进行类型的安全检查,这些是宏定义做不到的

一般把内联函数定义定义在头文件里,当编译器看到这个定义时,它把函数类型(函数名+返回值)和函数体放到符号表里,当使用函数时,编译器检查以确保调用是否正确的且返回值被正确使用,然后将函数调用替换为函数体,因而消除了开销,内联代码的确占用空间,要是函数比较小,就可以用内联

 

 

在头文件里,内联函数默认为内部连接---即它是static ,并且只能再它被包含的编译单元里面看到,因此,只要他们在不相同的编译单元中声明,在内联函数和全局函数之间用相同的名字,在连接时也不会发生冲突

 

 

内联对于函数和编译器:

对于任何函数,编译器在它的符号表里放入函数类型(包括函数名字和参数类型及其返回值类型),另外,编译器看到内联函数和内联函数的分析没有错时,函数的代码也被放入符号表里,代码是以源程序的形式存放还是以编译过的汇编指令形式存放取决于编译器

调用一个内联函数时,编译器首先确保正确,即所有的参数类型必须是正确的或者编译器

必须能够将类型转换为正确类型,并且返回值在目标表达式里应该是正确的类型或者可以改变为正确的类型,预处理器就不能进行类型安全检查和进行转换

假如内联函数是成员函数,对象的地址(this)指针就会被放到合适的位置,这当然也是预处理器不能做到的

 

 

局限性:

任何种类的循环都会被认为太复杂而不被拓展为内联函数

——————————————————————————————————————

《完美c++

1.可以在类的声明中给出成员函数的完整定义,这种定义方式被称为内联函数定义,

一般来讲,内联函数只用于函数体很短的成员函数定义,内联函数在定义上与一般函数不同,

而且编译器还会对内联函数做特殊处理,在编译时,内联函数的代码回被直接插入到每个调用函数内联的地方,从而减少函数的开销

缺点:内联函数只能在定义它的源文件中使用

          只由在函数体较短的函数应当采用内联形式,对于函数体较长的函数,内联形式的使用反而会降低效率,因为这会导致大片代码的复制

———————————————————————————————————————

c/c++编程指南》

1.用内联替代宏代码

支持内联:提高函数的执行效率

c程序中用宏代码来提高执行效率,宏代码本身不是函数,但它用起来像函数,预处理器用复制宏代码的方式代替函数调用,省去了参数压栈,生成汇编语言的CALL调用,返回参数 ,执行return 等过程,从而提高了速度。宏代码容易出错,即产生意想不到的边际效应

关于inline 函数的总结_第1张图片


1.还有一点:宏代码无法操作类的私有成员

C++中的内联机制既具备宏代码的效率,又增加了安全性,可以自由操作类的数据成员,

所以在c++程序中,应该用内联函数取代所有的宏代码,但是断言:“assert”是例外,assert是仅在Debug版本起作用的宏,用于检查不应该发生的情况,为了不在程序的Debug版本和Release 版本引起差别,assert不应该产生任何副作用,如果assert是函数,由于函数调用会引起内存,代码的变动,那么将导致Debug版本和Release版本存在差异,所以assert不是函数,而是宏

 

关键字inline必须与函数定义体放在一起才能使函数成为内联,如果只将inline 放在函数声明前将不起任何作用

 

Inline 是一种用于实现的关键字,而不是用于声明的关键字,所以最好在函数的声明里面不要出现inline 关键字,函数的声明和定义不能混为一谈

 

 

定义在类里面的函数自动成为内联函数

慎用内联:

内联是以代码膨胀为代价,仅仅省去函数调用的开销,

如果函数体内的代码比较长,使用内联会导致内存消耗代价较高

 

如果函数体内出现循环,那么执行函数体内代码的事件比函数调用开销大,

 

类的构造函数和析构函数容易让人误解为使用内联更有效,但是要当心构造函数和析构函数可能会隐藏一些行为,所以最好不要将类的构造函数和析构函数放到类声明中。

 

 

 

 

 





你可能感兴趣的:(书籍笔记)