函数
内联(inline)函数
在c++中inline
关键字可以用来修饰函数,用来在编译阶段请求编译器将函数体的代码直接插入调用处,而不是通过函数调用的机制。
-
用途:
在频繁调用一个函数时,由于函数调用产生的开销是很大的,而用inline
函数实际上是用空间换取时间的方式不去堆栈上调用函数,加快调用。 -
适用函数:短小且经常调用的函数
-
优点: 效率提高
-
缺点:可能适得其反,甚至,编译器直接不允许这么操作
几点说明:
- 当代编译器可以智能的为我们自动内联函数。
- 我们将函数
inline
只是一种请求,不是强制,可能编译器会否认这种inline。
函数模板
C++提供了函数模板(function template)。
函数模板实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。
定义函数模板的一般形式为
template<typename T>
通用函数定义
或
template <class T>
template<typename T>
T myMax(T a,T b){
return a>b?a:b;
}
template<class T>
T myMin(T a,T b){
return a<b?a:b;
}
int main(){
int a = myMax(1, 5);
double b = myMin(7.5, 10.8);
cout<<a<<endl;
cout<<b<<endl;
return 0;
}
具有默认参数值的函数
在C++中定义函数时,允许给参数指定一个缺省的值。在调用函数时,若明确给出了这种实参的值,则使用相应实参的值。若没有给出相应的实参,则使用缺省的值。
说明:
- 不可以靠左边缺省
void fun(int x=0,int y); // error
void fun(int x,int y=0,int z); //error
- 函数原型说明时可以不加变量名
void fun(int=0,int=1,double=2.0);
- 只能给出一次缺省值
void fun(int=0,int=1);
void fun(int a=0,int b=1){cout<<a+b+c<<endl;} //error,重复定义,哪怕一样也不可以。
注意:
void f(){cout<<"1"<<endl;}
void f(int x=0){cout<<"2"<<endl;}
int main(){
f(); //error,模糊调用
f(); //error,模糊调用
return 0;
}
作用域(scope)
作用域是指程序中所说明的标识符在哪一个区间内有效,即在哪一个区间内可以使用该标识符。
- 块作用域
{}
具有块作用域的标识符在其作用域内,将屏蔽包含本块的同名标识符,即变量名相同,局部更优先。
int x = 1;
{
int x=10;
cout<<x<<endl; // 10;
}
- 函数原型作用域
在函数原型的参数表中说明的标识符所具有的作用域称为函数原型作用域,从其说明处开始,到函数原型说明的结束处结束
由于所说明的标识符与该函数的定义及调用无关,编译系统对函数声明中的变量名是忽略的,即使在调用函数时也没有为它们分配存储单元。可以在函数原型说明中只作参数的类型说明,省略参量名。
int max(int,int);
- 文件作用域
在函数外定义的变量称为全局变量。
- 其缺省的作用范围是:从定义全局变量的位置开始到该源程序文件结束。
int x;
int main(){
cout<<x;
cout<<y; //error,此时还未定义。
return 0;
}
int y;
-
当局部变量与全局变量同名时,局部变量优先。
-
在块作用域内可通过作用域运算符“::”来引用与局部变量同名的全局变量。
int x = 1;
int main(){
int x = 2;
cout<<x<<endl; // 2
cout<<::x<<endl; // 1
return 0;
}
注意:
不要过多的使用全局变量(尽量不用):
-
全局变量在程序的全部执行过程中都占用存储单元,而不是仅在需要时才开辟单元。
-
降低了函数的通用性。如果将一个函数移到另一个文件中,还要将有关的外部变量及其值一起移过去。但若该外部变量与其他文件的变量同名,就会出现问题,降低了程序的可靠性和通用性。一般要求把程序中的函数做成一个封闭体,只通过“实参——形参”的渠道与外界发生联系外,这样的程序移植性好,可读性强。
-
函数作用域
-
类作用域
存储类别(storage duration)
- 静态存储:在程序运行期间有固定的存储空间,直到程序运行结束。
- 动态存储:在程序运行期间根据需要分配存储空间,函数结束后立即释放空间。若一个函数在程序中被调用两次,则每次分配的单元有可能不同。
变量
全局变量
- 在函数外定义的变量称为全局变量。
其缺省的作用范围是:从定义全局变量的位置开始到该源程序文件结束。
全局变量是在函数的外部定义的**,编译时分配在静态存储区**,如果未赋初值,其值为0或空字符。
- 1.
extern
关键字
当在一个文件中要引用另一个文件中的全局变量或在同一个文件中全局变量定义之前要引用它时,可用extern
作说明,相当于扩展全局变量的作用域。
这也就是缺省的状态,也就是说默认就是extern
修饰的。
- 在一个文件内提前声明全局变量
如果去掉extern
这个关键字,值就是乱的了
int main(){
extern int a,b;
cout<<a<<" "<<b<<endl; // 1 2
return 0;
}
int a=1,b=2;
- 在多文件的程序中声明外部变量及调用另一个.cpp文件中的函数
// a.cpp
#include<iostream>
using namespace std;
int a;
int main(){
extern int myPower(int); // 声明将要调用在b.cpp文件中定义的函数
int m;
cin>>a>>m;
int ans = myPower(m);
cout<<ans<<endl;
return 0;
}
// b.cpp
// 在a.cpp文件中的全局变量a的声明
extern int a;
int myPower(int n){
int temp = 1;
for(int i=1;i<=n;i++){
temp*=a;
}
return temp;
}
- 2.
static
关键字
限定全局变量仅能在本文件中引用,即使在其它文件中用extern说明也不能使用。相当于限制了全局变量的作用域范围。
static
修饰全局变量:在函数外部定义,存储在静态存储区,只限在本文件中使用,与extern
对应。
局部变量
-
自动变量(
auto
):默认,存储在动态区.auto
关键字可以省略。 -
静态局部变量(
static
):-
静态局部变量在静态存储区内分配存储单元。在程序整个运行期间都不释放。
编译时为静态局部变量赋初值,只赋初值一次,在程序运行时它已有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。
如果在定义局部变量时不赋初值的话,对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符型变量)。 -
虽然静态局部变量在函数调用结束后仍然存在,但其他函数不能引用它(可见性仍虽然是局部的,只是生命周期变了)。
-
如不是必需,不要用静态局部变量 。
-
-
寄存器变量(
register
)
一般情况下,变量的值是存放在内存中的。当程序中用到哪一个变量的值时,由控制器发出指令将内存中该变量的值送到CPU中的运算器。经过运算器进行运算,如果需要存数,再从运算器将数据送到内存存放。
为提高执行效率,C++允许将局部变量的值放在CPU中的寄存器中,需要用时直接从寄存器取出参加运算,不必再到内存中去存取。这种变量叫做寄存器变量,用关键字register
声明。
注意:
在程序中定义寄存器变量对编译系统只是建议性,不是强制性的。
现在使用的编译系统能够自动识别使用频繁的变量,将这些变量放在寄存器中。编程时,不必要再使用register声明变量,交给编译器去自动处理。