C++ 语言篇 Inline

Inline

1.C/C++为了解决频繁调用小函数消耗栈空间的问题,引入内联函数。栈空间就是存放局部数据的内存空间。大量调用函数会造成栈空间不足而程序出错,inline避免了调用函数对栈内存重复开辟所带来的消耗。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
include <string>
using std::string;

include <iostream>
using std::cout; using std::endl;

//inline version: find the shorter of two strings
inline const string &
shorterString(const string &s1, const string &s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}

int main()
{
string s1("successes"), s2("failure");
cout << shorterString(s1, s2) << endl;
// call the size member of the string returned by shorterString
cout << shorterString(s1, s2).size() << endl;
// equivalent code as generated by the call to inline version
// of shorterString
cout << (s1.size() < s2.size() ? s1 : s2) << endl;
return 0;
}

2.inline使用限制:只能是小函数,不能包含复杂的结构控制语句,不能是递归函数。如果inline函数体内代码多或者出现循环,执行代码的时间比函数调用的开销大,那么内联的效率很低。另外,每次调用inline函数都要复制代码,使程序总代码量增大,消耗内存。

3.inline只是对编译器的建议,最后是否内联,看编译器的意思,如果不复杂就会在调用点展开,真正内联。并不是声明了内联就会内联。

4.建议inline函数的定义放在头文件中。因为在不同的单元都会调用内联函数,所以放在头文件中最合适。声明和定义要一致,最好定义和声明是一样的,如果不一样,由编译器决定。内联函数最好放在文件头。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 头文件
ifndef EXAMPLE_H
define EXAMPLE_H
// 包含于多个源文件的函数必须为 inline
inline int sum(int a, int b)
{
return a + b;
}
endif

// 源文件 #2
include "example.h"
int a()
{
return sum(1, 2);
}

// 源文件 #1
include "example.h"
int b()
{
return sum(3, 4);
}

5.类中、结构体、联合中定义的函数,不管是成员函数还是非成员的友元函数,都为隐式的inline函数,即缺省都是内联的。如果未在类内给出定义,又想内联该函数,在类外要加inline。

直接在类声明中定义成员函数,虽然书写方便,但是不是很好的编程风格。

1
2
3
4
class A
{
public:void Foo(int x, int y) { } // 自动地成为内联函数
}

应该改成:

1
2
3
4
5
6
7
8
// 头文件
class A
{
public:
void Foo(int x, int y);
}
// 定义文件
inline void A::Foo(int x, int y){}

6.inline 必须和函数定义体放在一起才能起作用,跟声明放在一起没有作用。所以inline是一种用于实现的关键字,而不是用于声明的关键字。声明和定义不可以混为一谈,用户没有必要知道函数是否需要内联。

7.类的构造函数和析构函数会隐藏一些行为,比如执行了基类或者成员对象的构造函数或析构函数。不要将构造/析构函数的定义体放在声明中,编译器会根据函数的定义体,自动取消不值得的内联,进一步说明了inline不应该在函数的声明中。

Thanks for Support.