C++高级编程之——函数重载、内联、缺省参数、隐式转换( 五 )


副作用 。如果 assert 是函数 , 由于函数调用会引起内存、代码的变动 , 那么将导致 Debug
版本与 Release 版本存在差异 。所以 assert 不是函数 , 而是宏 。(参见 6.5 节“使用断言”)
8.5.2 内联函数的编程风格
关键字 inline 必须与函数定义体放在一起才能使函数成为内联 , 仅将 inline 放在
函数声明前面不起任何作用 。如下风格的函数 Foo 不能成为内联函数:
inline void Foo(int x, int y); // inline 仅与函数声明放在一起
void Foo(int x, int y)
{

}
而如下风格的函数 Foo 则成为内联函数:
void Foo(int x, int y);
inline void Foo(int x, int y) // inline 与函数定义体放在一起
{

}
所以说 , inline 是一种“用于实现的关键字” , 而不是一种“用于声明的关键字” 。
一般地 , 用户可以阅读函数的声明 , 但是看不到函数的定义 。尽管在大多数教科书中内
联函数的声明、定义体前面都加了 inline 关键字 , 但我认为 inline 不应该出现在函数
的声明中 。这个细节虽然不会影响函数的功能 , 但是体现了高质量 C++/C 程序设计风格
的一个基本原则:声明与定义不可混为一谈 , 用户没有必要、也不应该知道函数是否需
要内联 。
定义在类声明之中的成员函数将自动地成为内联函数 , 例如
class A
{
public:
void Foo(int x, int y) { … } // 自动地成为内联函数
}
将成员函数的定义体放在类声明之中虽然能带来书写上的方便 , 但不是一种良好的编程
风格 , 上例应该改成:
// 头文件
class A
{
public:
void Foo(int x, int y);
}
// 定义文件
inline void A::Foo(int x, int y)
{

}
8.5.3 慎用内联
内联能提高函数的执行效率 , 为什么不把所有的函数都定义成内联函数?
如果所有的函数都是内联函数 , 还用得着“内联”这个关键字吗?
内联是以代码膨胀(复制)为代价 , 仅仅省去了函数调用的开销 , 从而提高函数的执行效率 。如果执行函数体内代码的时间 , 相比于函数调用的开销较大 , 那么效率的收获会很少 。另一方面 , 每一处内联函数的调用都要复制代码 , 将使程序的总代码量增大 , 消耗更多的内存空间 。以下情况不宜使用内联:
(1)如果函数体内的代码比较长 , 使用内联将导致内存消耗代价较高 。
(2)如果函数体内出现循环 , 那么执行函数体内代码的时间要比函数调用的开销大 。
类的构造函数和析构函数容易让人误解成使用内联更有效 。要当心构造函数和析构
函数可能会隐藏一些行为 , 如“偷偷地”执行了基类或成员对象的构造函数和析构函数 。
所以不要随便地将构造函数和析构函数的定义体放在类声明中 。
一个好的编译器将会根据函数的定义体 , 自动地取消不值得的内联(这进一步说明
了 inline 不应该出现在函数的声明中) 。

C++高级编程之——函数重载、内联、缺省参数、隐式转换

文章插图
 




推荐阅读