C/C++中inline/static inline/extern inline的区别及使用

引入内联函数的目的是为了解决程序中函数调用的效率问题,也是用内联函数取代带参宏定义(函数传参比宏更加方便易用)

inline关键字用来定义一个类的内联函数。

在类体中和类体外定义成员函数是有区别的:在类体中定义的成员函数为内联(inline)函数,在类体外定义的不是。如果你既希望将函数定义在类体外部,又希望它是内联函数,那么可以在声明函数时加 inline 关键字.在类体内部定义的函数也可以加 inline 关键字,但这是多余的,因为类体内部定义的函数默认就是内联函数.如果在类体外定义 inline 函数,则必须将类定义和成员函数的定义都放在同一个头文件中(或者写在同一个源文件中),否则编译时无法进行嵌入。

inline定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高。类的内联函数也是一个真正的函数,编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。然后进行一系列的相关检查,就像对待任何一个真正的函数一样。这样就消除了它的隐患和局限性。inline可以作为某个类的成员函数,当然就可以在其中使用所在类的保护成员及私有成员。

inline使用场景:(1)、可以使用inline函数完全取代表达式形式的宏定义;(2)、内联函数一般只会用在函数内容非常简单的时候,这是因为,内联函数的代码会在任何调用它的地方展开,如果函数太复杂,代码膨胀带来的恶果很可能会大于效率的提高带来的益处。

在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替换。显然,这种做法不会产生转去转回的问题,但是由于在编译时将函数体中的代码被替代到程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间开销上不像函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省。内联函数可减少cpu的系统开销,并且程序的整体速度将加快,但当内联函数很大时,会有相反的作用,因此一般比较小的函数才使用内联函数.

有两种内联函数的声明方法,一种是在函数前使用inline关键字,另一种是在类的内部定义函数的代码,这样的函数将自动转换为内联函数,而且没必要将inline放在函数前面。

内联是一种对编译器的请求,下面这些情况会阻止编译器服从这项请求:如果函数中包含有循环,switch或goto语句,递归函数,含有static的函数.

由此可以看出,内联函数和成员函数没什么区别,区别就在于怎样加快函数的执行速度而已。内联函数是浪费空间来节省时间的设置,因为函数的调用是很浪费时间的,写成内联函数可以在每次调用时用函数体内容代替函数调用,有点类似一个宏定义。当函数体语句较少,且没有复杂的循环语句,且调用次数较多时,就可以用内联函数。

内联函数从源代码层看,有函数的结构,而在编译后,却不具备函数的性质。编译时,类似宏替换,使用函数体替换调用处的函数名。一般在代码中用inline修饰,但是否能形成内联函数,需要看编译器对该函数定义的具体处理。

"static inline" means "we have to have this function, if you use it, but don‘t inline it, then make a static version of it in this compilation unit". "extern inline" means "I actually _have_ an extern for this function, but if you want to inline it, here‘s the inline-version".

static是以前C的用法.目的是让该关键字标识的函数只在本地文件可见,同一个程序的其它文件是不可见该函数的.换句话说,就算你其它文件里包含了同名同参数表的函数定义的话,也是不会引起函数重复定义的错误的.因为static是仅在当前文件可见。

static inline,静态内联函数,它不使用函数调用,直接将汇编代码插入在调用该函数处。

static inline,可以把它认为是一个static的函数,加上了inline的属性。static inline函数和static函数一样,其定义的范围是local的,即可以在程序内有多个不同的定义(只要不位于同一个文件内即可)。

static inline的内联函数,一般情况下不会产生函数本身的代码,而是全部被嵌入在被调用的地方。如果不加static,则表示该函数有可能会被其他编译单元所调用,所以一定会产生函数本身的代码。所以加了static,一般可令可执行文件变小。Linux内核使用的inline函数大多被定义为static 类型。一个"static inline"函数促使编译程序尝试着将其代码插入到所有调用它的程序中。

extern inline表示该函数是已声明过的了.由于函数本身可以声明多次,所以extern对函数的影响仅仅把函数的隐藏属性显式化了. extern 对于非函数的对象是有用的,因为对象声明时会带来内存的分配,而用 extern就表示该对象已经声明过了,不用再分配内存。

extern inline函数的应用范围比较狭窄,一般不建议使用。

以上内容主要整理自:

1. http://www.cnblogs.com/pengyingh/articles/2405718.html

2. http://stackoverflow.com/questions/216510/extern-inline

3. http://wenku.baidu.com/link?url=QVc0SQBmFKDjcz65nQRe5wqsaY-rBp89VAu9iX6aCm2avMORW-IeGf_zYxFYRf4vNi7P-G3eFc7sx_FzzUh2r2EoXEGajf9MWxVm1_sJsVO

以下为测试代码:

static_inline.h:

#ifndef FBC_MESSY_TEST_STATIC_INLINE_HPP_
#define FBC_MESSY_TEST_STATIC_INLINE_HPP_

class FastMath {
public:
	int round(float value) { //类体内部定义的函数默认就是内联函数,也可以加 inline 关键字,但这是多余的
		return (int)(value + (value >= 0 ? 0.5f : -0.5f));
	}

	inline int floor(float value); // 声明为内联函数
};

int FastMath::floor(float value)
{
	int i = round(value);
	float diff = (float)(value - i);
	return i - (diff < 0);
}

static inline int Ceil(float value)
{
	int i = (int)(value + (value >= 0 ? 0.5f : -0.5f));
	float diff = (float)(i - value);
	return i + (diff < 0);
}

void test_static_inline1();
void test_static_inline2();

#endif // FBC_MESSY_TEST_STATIC_INLINE_HPP_

static_inline.cpp:

#include "static_inline.hpp"
#include <iostream>

void test_static_inline1()
{
	float a = 4.1, b = 4.9;

	FastMath math;
	int ret1 = math.round(a);
	int ret2 = math.floor(a);
	int ret3 = math.round(b);
	int ret4 = math.floor(b);

	std::cout << ret1 << "   " << ret2 << "    " << ret3 << "    " << ret4 << std::endl;
}

void test_static_inline2()
{
	float a = 4.1, b = 4.9;

	int ret1 = Ceil(a);
	int ret2 = Ceil(b);

	std::cout << ret1 << "    " << ret2 << "    " << std::endl;
}

GitHubhttps://github.com/fengbingchun/Messy_Test

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

原文地址:https://www.cnblogs.com/xkiwnchwhd/p/10317930.html

时间: 2024-10-31 15:59:35

C/C++中inline/static inline/extern inline的区别及使用的相关文章

转载 浅谈C/C++中的static和extern关键字

浅谈C/C++中的static和extern关键字 2011-04-21 16:57 海子 博客园 字号:T | T static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.extern "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern "C"来说明.本文主要介绍C/C++中的static和extern关键字. AD: static是C++中常用的修饰符,它被用来控制变量的存贮方

PHP中new static()与new self()的区别异同分析

本文实例讲述了PHP中new static()与new self()的区别异同,相信对于大家学习PHP程序设计能够带来一定的帮助. 问题的起因是本地搭建一个站.发现用PHP 5.2 搭建不起来,站PHP代码里面有很多5.3以上的部分,要求更改在5.2下能运行. 改着改着发现了一个地方 return new static($val); 这尼玛是神马,只见过 return new self($val); class A { public static function get_self() { re

浅谈C/C++中的static和extern关键字 转

原文:http://developer.51cto.com/art/201104/256820.htm static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.extern, "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern "C"来说明. 一.C语言中的static关键字 在C语言中,static可以用来修饰局部变量,全局变量以及函数.在不同的情况下static的作用不尽相同.

PHP 中 new static 和 new self 的区别

        今天老大在公司 问了一下  new static  和 new self 的区别 公司十个程序 竟然没有一个回答上来 后面画面自补 ... 本屌丝回家后 就百度了解了下 这二者区别 : 使用 self:: 或者 __CLASS__ 对当前类的静态引用,取决于定义当前方法所在的类: 使用 static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的.也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用. 简单通俗的来说, self就是写在哪个类里面, 实

OC中使用 static 、 extern、 const使用

static static用于定义静态变量,静态变量只会被初始化一次,并且直到程序销毁时才会释放 static NSString *str = @"asdfa"; const const用于定义常量 NSString* const URL = @"www.baidu.com"; extern(外部变量) extern表明定义的变量是外部变量 .h文件 extern NSString * const king; .m文件 NSString * const king =

PHP中new static() 和 new self() 的区别

self 指的是self所在的类 new static 实例化的是当前使用的类,有点像$this ,从堆内存中提取出来. 还是通过实例说明一下: class A {    public static function get_self() {        return new self();    } public static function get_static() {        return new static();    }} class B extends A {} echo

static 和extern关键字

static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.extern "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern "C"来说明.本文主要介绍C/C++中的static和extern关键字. static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.extern, "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方

内联函数:static inline 和 extern inline 的含义

引入内联函数的目的是为了解决程序中函数调用的效率问题. 函数是一种更高级的抽象.它的引入使得编程者只关心函数的功能和使用方法,而不必关心函数功能的具体实现:函数的引入可以减少程序的目标代码,实现程序代码和数据的共享.但是,函数调用也会带来降低效率的问题,因为调用函数实际上将程序执行顺序转移到函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方.这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行.因此,函数调用要有一定的

const static extern inline volatile explicit

static关键字至少有下列n个作用: (1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值: (2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问: (3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内: (4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝: (5)在类中的static成员函数属于整个