2. 函数调用开销:调用前要先保存寄存器,并在返回点恢复;复制实参;程序必须转入一个新位置执行
3. 内联的目的是为了避免函数调用开销。函数指定为内联函数后,通常是将它在程序中每个调用点上"内联地"展开
4. 内联函数的优点是不用函数调用就能隐藏数据,仅此而已
5. inline关键字只是告诉编译器,函数可以内联展开执行,编译器可以自由选择是否内联
6. 非成员函数声明为内联在函数前面加关键字inline,这种函数被声明为内联函数后,其定义(or implementation)最好放在头文件中,除非此函数只在单个的源文件中使用。不放在头文件中,在其它源文件中调用此内联函数在连接时会出错。
7. 被隐式声明为内联:(1)定义出现在类定义中的成员函数;(2)被编译器创建的构造、析构、拷贝构造函数、赋值操作运算
8. 内联函数应在头文件中定义,这样可以确保在调用函数时使用相同的定义,并且保证在调用点该函数的定义对编译器可见
不适合做内联函数的情况:递归调用、函数包含循环如(for,while等)、函数代码过大
9. 如果将成员函数的定义放在类定义的外面,就像下面的Pop一样,它将自动成为非内联。当然如果你仍然想使之内联,你
必须在其定义的前面添加关键字inline。在这种情况下,必须记住,当编译器编译调用此函数的代码时,它必须访问此定义
(而不仅仅是访问类中的声明)。这就是为什么这样的定义通常放在由调用者包含的头文件中的原因
/****************************Header file: stack.h***********************/
#
if
!
defined(_080117_STACK_H_) //防止头文件被重复编译, 也可用#ifndef _080117_STACK_H_
#define _080117_STACK_H_
const int maxStack = 5 ; //const告诉编译器, maxStack的值永远不会改变
class IStack
{
public:
IStack():_top(0) {} //初始化堆栈顶部索引为0
void Push(int i);
int Pop(); //该函数在类外定义时被声明为内联函数,此时不要把inline加在此函数的声明前面
int Count() { return _top; } //Count()的执行在类IStack的定义中, 因此它被隐式声明为内联函数
int GetTop() { return _arr[_top-1]; } //GetTop()的执行在类IStack的定义中, 因此它被隐式声明为内联函数
private:
int _arr[maxStack]; //数组的大小必须为常量, 当数组为显式初始化时, 不必指定其大小
int _top;
} ;
#endif // end of _080117_STACK_H
#define _080117_STACK_H_
const int maxStack = 5 ; //const告诉编译器, maxStack的值永远不会改变
class IStack
{
public:
IStack():_top(0) {} //初始化堆栈顶部索引为0
void Push(int i);
int Pop(); //该函数在类外定义时被声明为内联函数,此时不要把inline加在此函数的声明前面
int Count() { return _top; } //Count()的执行在类IStack的定义中, 因此它被隐式声明为内联函数
int GetTop() { return _arr[_top-1]; } //GetTop()的执行在类IStack的定义中, 因此它被隐式声明为内联函数
private:
int _arr[maxStack]; //数组的大小必须为常量, 当数组为显式初始化时, 不必指定其大小
int _top;
} ;
#endif // end of _080117_STACK_H
/****************************Source file: stack.cpp***********************/
#include
"
stack.h
" //包含自定义头文件
#include < cassert >
#include < iostream >
///成员函数的定义在类的外面时,它的名字必须带有类名加双冒号,如 IStack::
//通过NDEBUG=1编译去掉断言,只要没有定义NDEBUG,此断言就会检查它的参数的逻辑真实性,断言失败表明程序有漏洞
void IStack::Push( int i) //Push方法的定义在类的外面,因此该方法自动变成了非内联方法(函数)
{
assert(_top<maxStack); //断言检查
_arr[_top]=i;
++_top;
std::cout<<"Element "<<i<<" is pushed into stack!\n";
}
inline int IStack::Pop() //Pop方法的定义在类的外面,通过在该定义的前面加inline变成了内联方法(函数)
{
assert(_top>0);
--_top;
return _arr[_top];
}
void main()
{
IStack stack;
stack.Push(1);
stack.Push(2);
std::cout<<"Top element "<<stack.GetTop()<<std::endl; //内联展开后等价于stack._arr[_top-1]
std::cout<<"Count "<<stack.Count()<<std::endl; //内联展开后等价于stack._top
std::cout<<"Popped "<<stack.Pop()<<std::endl;
std::cout<<"Popped "<<stack.Pop()<<std::endl;
std::cout<<"Call top when out of boundrary! "<<stack.GetTop()<<std::endl;
std::cout<<"Count "<<stack.Count()<<std::endl;
}
#include < cassert >
#include < iostream >
///成员函数的定义在类的外面时,它的名字必须带有类名加双冒号,如 IStack::
//通过NDEBUG=1编译去掉断言,只要没有定义NDEBUG,此断言就会检查它的参数的逻辑真实性,断言失败表明程序有漏洞
void IStack::Push( int i) //Push方法的定义在类的外面,因此该方法自动变成了非内联方法(函数)
{
assert(_top<maxStack); //断言检查
_arr[_top]=i;
++_top;
std::cout<<"Element "<<i<<" is pushed into stack!\n";
}
inline int IStack::Pop() //Pop方法的定义在类的外面,通过在该定义的前面加inline变成了内联方法(函数)
{
assert(_top>0);
--_top;
return _arr[_top];
}
void main()
{
IStack stack;
stack.Push(1);
stack.Push(2);
std::cout<<"Top element "<<stack.GetTop()<<std::endl; //内联展开后等价于stack._arr[_top-1]
std::cout<<"Count "<<stack.Count()<<std::endl; //内联展开后等价于stack._top
std::cout<<"Popped "<<stack.Pop()<<std::endl;
std::cout<<"Popped "<<stack.Pop()<<std::endl;
std::cout<<"Call top when out of boundrary! "<<stack.GetTop()<<std::endl;
std::cout<<"Count "<<stack.Count()<<std::endl;
}
输出结果:
Element 1 is pushed into stack!
Element 2 is pushed into stack!
Top element 2
Count 2
Popped 2
Popped 1
Call top when out of boundrary! -858993460
Count 0