2020-03-08

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

  • 这里指出vlnt是随时可能发生变化的每次使用它的时候,必须从vlnt的地址中读取。因
  • 而编译器生成的代码会重新从vlnt的地址读取数据。

  • 优化的做法是:由于编译器发现两次从vlnt中读取的代码之间没有对vlnt进行过操作,
  • 它会自动把上次读取的数据发到b中。*/
    /2、## 标题olatile关键字常用在以下几个地方:
    (1)在中断服务程序中修改的供其他程序检测的变量加volatile;
    (2)多个任务环境下各任务间共享标志为应加关键字volatile;
    (3)存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它读写都可能有不同的意义;
    /
    /*3、volatile指针
  • 和const修饰词一致,const有常量指针和指针常量的说法,volatile也有相应的概念。
  • (1)修饰由指针指向的对象、数据是const或volatile
  •  const char *cpch;//数据是const类型,这里const修饰的是变量
    
  •  volatile char *vpch;数据是volatile类型
    
  • (2)指针自身的值——一个代表地址的整数变量,是const、volatile类型
  •  char * const pcch //这里修饰的指针,指针是const类型
    
  •  char * volatile pvch // 这里volatile修饰的是指针,把pvch这个指针修饰为volatile类型*/
    

/* 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
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访问规则*/
//静态数据成员的初始化与普通数据成员的初始化不同
/静态数据成员的初始化:
<数据类型> <类名> ::<静态数据成员名> = 值;
/
/类的静态数据成员有两种访问方式:
① <类对象名>.<静态数据成员名>;
exp : MyClass M ;M.sumx;
② <类名> :: <静态数据成员名>;
/
/(2)静态成员函数
静态成员函数可以在类内定义,也可以在类内声明,类外定义,当在类外定义时,不能再使用static关键字作为前缀。
静态成员函数的调用方法:
① 类名::静态成员函数
exp:MyClass::getSum();
②对象.静态成员函数
MyClass M;
M.getSum();
/
/* 通过对象调用静态函数需要注意:
①通过对象访问静态成员函数的前提条件为对象已经建立;
②静态成员函数的访问权限同普通成员函数一样;
③静态成员函数也可以省略参数,使用默认形参值,以及进行重载。*/
/静态成员函数与普通成员函数在使用上的区别:由于静态成员函数在类中只有一个拷贝,因此他访问对象的成员
要受到一些限制:静态成员函数可以直接访问类中说明的静态成员,但不能直接访问类中的非静态成员;
如果要访问非静态成员,必须通过参数传递的方式得到相应的对象,在通过对象来访问。还需要注意的是:由于静态
成员独立于对象存在,因此静态成员没有this指针。
/
/virtual关键字************/
//加了virtual关键字的函数就是虚拟函数,

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值