C++中的常用关键字

*volatile关键字
1、volatile常量指针

private:

        volatile int vlnt = 10;
        int a = vlnt;
        int b = vlnt;

这里指出vlnt是随时可能发生变化的每次使用它的时候,必须从vlnt的地址中读取。因而编译器生成的代码会重新从vlnt的地址读取数据。它会自动把上次读取的数据发到b中。
2、volatile关键字常用在以下几个地方:
(1)在中断服务程序中修改的供其他程序检测的变量加volatile;
(2)多个任务环境下各任务间共享标志为应加关键字volatile;
(3)存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它读写都可能有不同的意义;
3、volatile指针
和const修饰词一致,const有常量指针和指针常量的说法,volatile也有相应的概念。
(1)修饰由指针指向的对象、数据是const或volatile

//数据是const类型,这里const修饰的是变量
const char *cpch;
//数据是volatile类型
volatile char *vpch;

(2)指针自身的值——一个代表地址的整数变量,是const、volatile类型

//这里修饰的指针,指针是const类型
char * const pcch 

//修饰为volatile类型
char * volatile pvch 

4、注意

  • (1)可以把非volatile int 赋值给volatile int 变量,但是不能把非volatile对象赋值给volatile对象
  • (2)除了基本类型外,对用户定义的类型也可以用volatile类型进行修饰
  • (3)C++ 中一个有volatile标识的类只能访问它接口的子集,一个类的实现者控制的子集。用户只能用const_cast
  • 来活动的对类型接口的完全访问。此外,volatile向const一样会从类传递给它的成员。
    5、多线程下的volatile
  • 有些变量是用volatile关键字声明的。当两个线程都要用到某一个变量且该变量的值会被改变时,应该使用volatile声
  • 明,该关键字的作用是防止优化编译器把变量内存装入到CPU寄存器中。如果变量被装入寄存器中,那么可能一个使用内存中
  • 的变量,一个使用寄存器中变量,这会造成程序的错误执行。volatile的意思是让编译器每次操作该变量时,一定要从内存
  • 中真正取出,而不是使用已经存在于寄存器中的值,如下:
 volatile bool bStop  = false;
  • (1)在一个线程中
while(!bStop)
      {
           ……
      }
           bStop = false;
       return;
  • (2)在另一个线程中,要终止上面线程的循环:
 bStop = True;
   while(bStop)
        {
              ……
       }

等待上面线程的终止,如果bStop不用volatile声明,那么这个循环将是一个死循环,因为bStop已经读取到 寄存器中,寄存器中bStop的值永远不会变成false,加上volatile,程序在执行时,每次从内存中读取bStop的值,就不 会变成死循环。这个关键字是用来设定某个对象的存储位置在内存中,而不是寄存中。因为一般的对象编译器可能会将其的拷贝放在寄存器中用 以加快指令的执行速度。
const关键字
1、基本概念

  • 关键字const用来定义常量,如果一个变量被const修饰,那么它的值就不会再改变。与#define预编译指令相比,
  • const修饰符有以下优点:
  • (1)预编译指令只是对值进行简单的替换,不能进行累心检查;
  • (2)可以保护被修饰的东西,防止意外修改,增强程序的健壮性;
  • (3)编译器通常不为普通const变量分配存储空间,而是将他们保存在符号表中,这使得他成为一个编译期间的常量,
  • 没有存储和读内存的操作,使得它的效率也更高。*/
    2、const的基本用法
  • (1)修饰局部变量
const int n = 5;
int const n = 10;

两种写法是一样的,都表示变量n不能修改,需要注意的是,用const修饰变量时,一定要对变量进行初始化,否则就不能再进行赋值了
修饰常量静态字符

 const char * str = "shijiediyichadan"

(2)常量指针和指针常量
常量指针是指针指向的内容是常量,可以有以下两种定义方式:

 const int * n;
 int const * n;

需要注意以下两点:
①常量指针说的是不能通过这个指针改变变量的值,但是可以通过其他的引用来改变变量的值

int a = 5;
const int * n = &a;
a = 6;

②常量指针指向的值不能改变,但这不意味着指针本身不能改变,常量指针可以指向其他地址

 int a = 5;
 int b = 10;
  const int *n = &a;
  //值不能变,但指针指向的地址可以改变
  n = &b;

指针常量:指针本身是一个常量,不能指向其他地址,写法如下:

 int *const n;

需要注意的是,指针常量指向那个的地址是不能改变的,但是地址中保存的值是可以改变的,可以通过其他指向该地址的指
针来修改

 int a = 5;
 int *p = &a;
 int *const n = &a;

这里n是一个只能指向a的指针,不能再指向其它的指针。但它指向的指针中的内容却是可以改变的。

 *p = 8;

指向常量的常指针:指针指向的位置不能改变,也不能通过这个指针改变常量的值,但是依然可以通过其它普通指针改变常量的
值。

  const int *const p;

//第一个const说明指针指向的是一个常量,第二个const说明p值是一个指针常量,它只能指向固定的地址。
(3)修饰函数的参数
①防止修改指针指向的内容 (常量指针)

void stringCopy(char * strDestinaton,
                const char * strSource);

其中strSource是输入参数,strDestination是输出参数。给strSource加上const后,如果函数体内的语句试图改动
strSource的内容,编译器将指出错误
②防止修改指针指向的地址(指针常量)

 void swap(int *const p1,int *const p2)

指针p1和指p2指向的地址都不能改变。
(4)修饰函数的返回值
如果给以"指针传递"方式的函数返回值加const指针修饰,那么函数的返回值的内容不能被修改,该返回值只能被赋值给加
const修饰的同类指针

 exp:
    const char *getString(void)
     //如下语句将出现一下错误:
   char * str = getString();
    //正确的用法是
    const char * str = getString();*****************/

static关键字
static 是C++中很常用的修饰符,它被用来控制变量的存储方式和可见性
1、面向过程的static
(1)静态全局变量
在全局变量/前加上关键字static,该变量就被定义为一个静态全局变量
exp:

  #include <iostream>
        using namespace std;
        void fun();
        static int n ;
        void main()
        {
            n = 20;
            printf("%d",n);
            fun();
        }
        void fun()
        {
            n ++ ;
            printf("%d",n);
        }

静态全局变量的特点:未经初始化的静态全局变量会被程序自动初始为0(在函数体内声明的自动变量的值是随机的,除非他被显式初始化,而在函数体外声明的而自动变量会被初始化为0);静态全局变量在声明它的整个文件都是可见 的,而在文件之外是不可见的
注意:全局变量和全局静态变量的区别:
①全局变量是不显式用static修饰的全局变量,全局变量默认有外部链接性的作用,作用域是整个工程,在一
个文件内定义的变量在另一个文件中,使用extern全局变量名声明,就可以使用全局变量。
② 全局静态变量是显式用static修饰的全局变量,作用域是声明此变量所在的文件,其他的文件使用extern声
明也不能使用
(2)静态局部变量

#include <iostream.h>
   void fun();
   void main()
   {
       fun();
       fun();
       fun();
   }
   void fun()
   {
        static int n = 10;
        printf("%d",n);
        n ++;
   }

静态局部变量解决问题:在函数体内定义了一个变量,没当程序运行到该语句时都会给该局部变量分配栈内存。但随着程
序退出函数体,系统就会收回栈内存,局部变量也相应失效。或者是在两次调用之间对变量的进行保存。
(3)静态函数

  #include <iostream.h>
    static void fun();//声明静态函数
    void main()
    {
        fun();
    }
    void fun()//定义静态函数
    {
        int n = 10;
        printf("%d",n);
    }

静态函数和普通函数的区别:它只能在声明它的文件中可见,不能被其他文件使用。其他文件中可以定义相同名字的函数,不会发生冲突。
2、面向对象的static
(1)静态数据成员
在类数据成员的声明前加上关键字static,该类的成员就是类内的静态数据成员。
静态数据成员的特点:
不管这个类创建了多少个对象,其静态成员在内存中只保留一份拷贝,这个拷贝为该类的所有对象共享。也就是说,静态数据成员是该类的所有对象共有的。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。所以静态数据成员的值对每个对象都是一样的,它的值可以更新。
静态数据成员和普通数据成员一样遵从public,protected,private访问规则
静态数据成员的初始化与普通数据成员的初始化不同
静态数据成员的初始化:
<数据类型> <类名> ::<静态数据成员名> = 值;
类的静态数据成员有两种访问方式:
① <类对象名>.<静态数据成员名>;

 class MyClass
 {
   ……
 }
 Myclass M ;
 M.sumx;

② <类名> :: <静态数据成员名>;
(2)静态成员函数
静态成员函数可以在类内定义,也可以在类内声明,类外定义,当在类外定义时,不能再使用static关键字作为前缀。
静态成员函数的调用方法:
① 类名::静态成员函数
exp:MyClass::getSum();
②对象.静态成员函数
MyClass M;
M.getSum();
通过对象调用静态函数需要注意:
①通过对象访问静态成员函数的前提条件为对象已经建立;
②静态成员函数的访问权限同普通成员函数一样;
③静态成员函数也可以省略参数,使用默认形参值,以及进行重载。
静态成员函数与普通成员函数在使用上的区别:由于静态成员函数在类中只有一个拷贝,因此他访问对象的成员要受到一些限制:静态成员函数可以直接访问类中说明的静态成员,但不能直接访问类中的非静态成员;
如果要访问非静态成员,必须通过参数传递的方式得到相应的对象,在通过对象来访问。还需要注意的是:由于静态
成员独立于对象存在,因此静态成员没有this指针。
thread关键字
thread_local :指出变量的持续性与它所属的线程的持续性是一致的。thread_local和线程的关系与静态变量和整个程序的关系一致。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值