static、const和关键字volatile

本文详细介绍了C++中的static关键字,包括static修饰变量和函数的特性,以及在C++类中的应用。同时,文章探讨了const修饰符的作用,如const变量的优化处理,并解释了volatile关键字在内存可见性方面的意义。此外,还讲解了const修饰引用和成员函数的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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成员函数。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值