(1)静态局部对象
一个变量如果位于函数的作用域内,但生命期跨越了这个函数的多次调用,这种变量往往很有用。则应该将这样的对象定义为 static(静态的)。
static 局部对象确保不迟于在程序执行流程第一次经过该对象的定义语句时进行初始化。这种对象一旦被创建,在程序结束前都不会撤销。当定义静态局部对象的函数结束时,静态局部对象不会撤销。在该函数被多次调用的过程中,静态局部对象会持续存在并保持它的值。
测试代码如下:
#include <iostream>
using namespace std;
size_t count_calls()
{
static size_t ctr = 0; // value will persist across calls
return ++ctr;
}
int main()
{
for (size_t i = 0; i != 10; ++i)
cout << count_calls() << " ";
cout<<endl;
return 0;
}
输出结果
tekken@tekken:~/C++WS$ ./a.out
1 2 3 4 5 6 7 8 9 10
在第一次调用函数 count_calls 之前,ctr 就已创建并赋予初值 0。每次函数调用都使加 1, 并且返回其当前值。 在执行函数 count_calls 时, 变量 ctr就已经存在并且保留上次调用该函数时的值。因此,第二次调用时,ctr 的值为1,第三次为 2,依此类推。
(2)内联函数
// find longer of two strings
const string &shorterString(const string &s1, const string &s2)
{
return s1.size() < s2.size() ? s1 : s2;
}
为这样的小操作定义一个函数的好处是:
• 阅读和理解函数 shorterString 的调用,要比读一条用等价的条件表达式取代函数调用表达式并解释它的含义要容易得多。
• 如果需要做任何修改, 修改函数要比找出并修改每一处等价表达式容易得多。
• 使用函数可以确保统一的行为,每个测试都保证以相同的方式实现。
• 函数可以重用,不必为其他应用重写代码。
但是,将 shorterString 写成函数有一个潜在的缺点:调用函数比求解等价表达式要慢得多。在大多数的机器上,调用函数都要做很多工作;调用前要先保存寄存器,并在返回时恢复;复制实参;程序还必须转向一个新位置执行。
inline 函数避免函数调用的开销
将函数指定为 inline 函数,(通常)就是将它在程序中每个调用点上“内联地”展开。假设我们将 shorterString 定义为内联函数,则调用:
cout << shorterString(s1, s2) << endl;
在编译时将展开为:
cout << (s1.size() < s2.size() ? s1 : s2)<< endl;
从而消除了把 shorterString 写成函数的额外执行开销。
inline const string &shorterString(const string &s1, const string &s2)
{
return s1.size() < s2.size() ? s1 : s2;
}
一般来说,内联机制适用于优化小的、只有几行的而且经常被调用的函数。大多数的编译器都不支持递归函数的内联。 一个 1200 行的函数也不太可能在调用点内联展开。
测试代码如下:
#include <iostream>
#include <string>
using namespace std;
inline const string &shorterString(const string &s1, const string &s2);
int main()
{
string a = shorterString("abc","abdc");
cout<<a<<endl;
return 0;
}
inline const string &shorterString(const string &s1, const string &s2)
{
return s1.size() < s2.size() ? s1 : s2;
}
输出结果:
tekken@tekken:~/C++WS$ ./a.out
abc
网友评论