C++关键字详解

话不多说,详细深入的学习一下C++各关键字,以便以后可以侃侃而谈。

注意:思维的广度和深度!

static 关键字

下面分4个场合来整理一下:修饰局部变量、全局变量、类中成员变量、类中成员函数。

静态全局变量

对于一个变量, 要从变量的作用域、生存周期、存储位置来分析回答。

static 修饰全局变量,限制了该变量的作用域当前文件,就是说他能在当前文件中作为全局变量被访问,但不能再其他文件中被访问,这里static是一个限定符。

也就是说,在声明全局的static变量时,static没有改变它的生存周期,也即存储位置(因为全局变量本来就存储在全局数据域),而是将变量的作用域限制在当前文件中。

  • 作用域:整个文件
  • 生存周期:程序的整个运行周期
  • 存储位置:全局数据区

静态全局变量 和 全局变量有什么区别? > 静态全局变量的作用域为当前文件,而全局变量可以被其他文件访问。

静态局部变量

静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次调用,直到下次赋新值。 静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化

  • 作用域:局部作用域
  • 生存周期:程序的整个运行周期
  • 存储位置:全局数据区

静态局部变量 和 局部变量 有什么区别? > 静态局部变量存储在全局数据区,不会随着程序退出函数体而销毁,并且只在声明时被初始化,后续将不再初始化。

静态数据成员(静态成员变量)

在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员。

  • 静态数据成员是该类的所有对象所共有的。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新;

  • 静态数据成员存储在全局数据区

  • 静态数据成员和普通数据成员一样遵从public,protected,private访问规则;

  • 静态数据成员不属于特定的类对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它。

静态成员函数

普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。静态成员函数由于不是与任何的对象相联系,因此它不具有this指针。

  • 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;

  • 静态成员函数与非静态成员函数的区别:

    非静态成员函数可以任意地访问静态成员函数和静态数据成员;静态成员函数不能访问非静态成员函数和非静态数据成员。

    这其实是因为 前面讲的, 普通的成员函数 一般都隐含this指针, 静态成员函数不与对象实例联系,不具有this指针。

  • 由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的提升;

const 关键字

当const用来修饰变量、指针、类对象、类中成员函数时...

const修饰变量

采用const修饰变量,功能是对变量声明为只读特性,并保护变量值以防被修改。

const修饰变量还起到了节约空间的目的,通常编译器并不给普通const只读变量分配空间,而是将它们保存到符号表中,无需读写内存操作,程序执行效率也会提高。

const修饰指针

C语言中const修饰指针有两种形式: 1. 用来限定指向空间的值不能修改; 2. 用来限定指针不可更改。

e.x.

1
2
3
4
5
int i = 5;
int j = 6;
int k = 7;
const int * p1 = &i; //定义1
int * const p2 =&j; //定义2

我的理解是 1 中 定义p1是个指向const int的指针,所以其指向空间的值将不能改变。 2 中const直接限定指针,故指针不能更改指向,但是其指向空间的值是可以改变的。

const 修饰类对象

被const修饰的类对象,既不能改变类中的成员变量,也不能调用类中任何非const成员函数。

e.x.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
using namespace std;
class A{
public:
void print(){
cout<<"Print()"<<endl;
}
void Test() const {
//_val++;//编译出错
cout<<"Test()"<<endl;
}
int _val;
};

int main(){
const A a;
a.print(); //编译出错,不能访问非const成员函数
a.Test(); //OK
a._val = 100; //编译出错,不能修改成员变量的值
}

const修饰类中成员函数

上例中的Test()函数被const修饰。

其本质就是 修饰该成员函数隐含的 this 指针。

const修饰成员函数 表示 此函数 不能对任何成员变量进行修改。(即上述代码中不能修改_val的值)

一般 const 写在函数的后面。

volatile关键字

定义为volatile的变量,是说这变量 可能会被意想不到地改变。

使用volatile关键字声明的变量或对象通常具有与优化、多线程相关的特殊属性。通常,volatile关键字是用来阻止(伪)编译器因误认某段代码无法被代码本身所改变,而造成的过度优化。

如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

int main(int argc,char* argv[])
{
int i=10;
//volatile int i = 10;
int a=i;
cout<<a<<endl;
_asm
{
mov dword ptr [ebp-4],80
}
int b=i;
cout<<b<<endl;
}

以上代码在生成release版本的时候,不会输出我们想要的答案,原因是release版本会对程序代码进行优化,在共享的环境下很容易出现问题。将 i 提前声明为volatile 就可以解决此问题。

其作用主要有以下两点: 1. 告诉compiler不能做任何优化。 2. volatile定义的变量如果在程序外被改变,每次都必须从内存中读取,而不能把他放在cache或寄存器中重复使用。


C++关键字详解
http://example.com/2022/11/15/C++关键字详解/
作者
Melrose Wei
发布于
2022年11月15日
许可协议