static
static修饰变量&修饰函数
在介绍static之前,先看下static修饰全局变量和局部变量的题。
#include<iostream>
using namespace std;
static int m;
void fun1()
{
static int n = 0;
n++;
printf("n = %d\n",n);
}
void fun2()
{
m = 0;
m++;
printf("m = %d\n",m);
}
int main()
{
int i;
for(i = 0; i < 10; i++)
{
fun1();
}
for(i = 0; i < 10; i++)
{
fun2();
}
system("pause");
return 0;
}
运行结果:
从运行结果可以看出,被static修饰的变量存储属性会发生改变,但被static修饰的全局变量和局部变量又有什么不同。这里先介绍下,变量的存储位置。
变量的存储位置
变量的缺省存储类型取决于它的申明位置。
1. 凡是在任何代码块之外的声明的变量总是存储于静态内存中。不属于堆栈内存,这类变量称为静态变量。静态变量在函数运行之前创建。
2. 在代码块内部声明的变量的缺省存储类型是自动的,存储于堆栈中。
注: 对于在代码块内部声明的变量,如果给他加上static关键字,可以使他的存储类型由自动转变为静态。具有静态存储类型的变量在整个程序执行过程中一直存在。而不仅仅是它所在的代码块执行的时候存在。修改变量的存储类型并不修改变量的作用域,它只能在该代码块内部按名字访问。
3. 寄存器变量:register 关键字。
static总结:
1. static修饰变量
static修饰全部变量,改变的是链接属性,将外部链接属性变为内部链接属性。即不能在其他源文件中被访问
static修饰局部变量,改变的是存储类型,从自动变量变为静态变量,同时影响了生命周期。变量的属性和作用域不受影响。
2. static修饰函数 改变的是链接属性,将外部链接属性变为内部链接属性
对于上面的程序,由于m是被static修饰的全局变量,所以它的存储类型并不改变,每次调用fun2()时,首先将m赋值为0,所以最后m的结果为1. 在调用fun1()时,由于n时被static修饰的局部变量,它的存储类型由自动变量变为静态变量,每次创建n时,由于静态区中已经存在n, 所以并不影响n的值,所以n最后的输出结果为1-10.
C++中的static
1. 类里面static修饰的成员,成为静态类成员。
2. 类的静态成员是该类型的所有对象对象所共享。
注:类的静态成员变量放在代码段,sizeof()不测量静态成员大小。
静态成员的定义和使用
class Date
{
public :
Date ()
{
cout<<"Date ()" <<endl;
++ sCount;
}
void Display ()
{
cout<<"year:" <<_year<< endl;
cout<<"month:" <<_month<< endl;
cout<<"day:" <<_day<< endl;
}
// 静态成员函数
static void PrintCount()
{
cout<<"Date count:" <<sCount<< endl;
}
private :
int _year ;
int _month ;
int _day ;
private :
static int sCount; // 静态成员变量, 统计创建时间个数
};
// 定义并初始化静态成员变量
int Date::sCount = 0;
void Test ()
{
Date d1 ,d2;// 访问静态成员
Date::PrintCount ();
}
注意 :1. 静态成员变量,静态成员变量的初始化。
2. 静态成员函数没有隐含this指针参数,所以可以使用类型 :: 作用域访问符直接调用静态成员函数。
问题:
1. 静态成员函数可以访问非静态成员函数?
2. 非静态成员函数可以访问静态成员函数?
注:1. 静态成员函数不能访问非静态成员,这是因为静态函数属于类而不是属于整个对象,静态函数中的 member可能都没有分配内存。静态成员函数没有隐含的this自变量。所以,它就无法访问自己类的非静态成员
2. 非静态成员函数中可以调用静态成员。因为静态成员属于类本身,在类的对象产生之前就已经存在了,所以在非静态成员函数中是可以调用静态成员的。
const和关键字volatile
const定义常量
在C语言中,当const 修饰一个标识符的时候我们说,这个标识符依然是一个变量,但是它具有常属性,不能被直接改变 。
在C++中,const修饰的标识符就是常量
const修饰变量时的优化处理
在这里可以看到num的值修改了,但输出结果并没有改变,这是怎么回事呢?
这里编译器在编译期间,对代码做了优化处理。当编译器看到num被const修饰时,从语义上,num是不希望被修改的值,优化时就将num的值存放寄存器中(提高访问的效率),使用时直接从寄存器取,所以即使内存中的值改变,寄存器也感知不到,所以输出结果为10.
当对代码做修改时,会出现什么情况呢?
当加上volatile时,输出结果为20. 那么volatile 有什么作用呢
volatile作用:
编译时不优化,执行时不缓存,每次需从内存中读出(保证内存的可见性)。
const修饰符
const的作用与#define相似,但它消除了#define的不安全性,因此C++ 建议用const取代#define定义常量。
(1) 指向常量的指针。
eg: const char* pc = "abcde";
由于使用了const,不允许改变指针所指的变量,因此pc[3] = 'x'; //是不允许的。 但是,由于pc是一个指向常量的普通指针变量,不是常指针。因此可以改变pc所指的地址。 eg: pc = "efgh";
(2) 常指针
把指针变量的所指的地址,而不是它指向的对象声明为常量。
eg: char* const pc = "abcd";
(3) 指向常量的常指针
这个指针变量所指的地址不能改变,它所指向的地址中的数据也不能改变。要声明一个指向常量的常指针,二者都要声明为const.
图解:
const引用
引用不是定义一个新的变量,而是给一个已经定义的变量重新起一个别名。
const修饰成员函数
在成员函数后面加const,const修饰this指针所指向的对象,也就是保证调用这个const成员函数的对象在函数内不会被改变。
注:
1. const对象可以调用const成员函数,不能调用非const成员函数1
2. 非const对象可以调用const成员函数和非const成员函数。