C++ part8

1、volatile关键字

在C++中,对volatile修饰的对象的访问,有编译器优化上的副作用:

  1. 不允许被编译器优化,提供特殊地址的稳定访问(只从内存中读取)。
  2. 有序性,编译器进行优化时,不能把对volatile对象前面的其他volatile语句放到他后面,反之也不行。也就是说volatile变量间的操作,是不会被编译器交换顺序的。

注意:
在多线程数据同步时,很多人会选择volatile来修饰全局的变量,使得线程同步。其实是不对的。由有序性可得,编译器可能对语句的位置进行交换,使得程序错误。

volatile bool flag = false;

//线程1
while(flag == false){
done();
}


//线程2
update();	//语句1
flag = true;	//语句2

上述代码中,编译时语句2可能和语句1调换位置,在多线程中,这可能会发生错误。

2、内联函数和宏定义

宏定义由预处理器实现,做一些简单的字符替换。
内联函数(inline)使用时,编译器将使用函数代码替换函数调用,这样就节省了函数调用的时间,但是增加了内存空间。

区别:

  1. 宏定义不能进行数据类型的检查,内联函数可以
  2. 宏定义展开发生在预编译阶段,内联函数展开发生在编译阶段
  3. inline作为类的成员函数可以调用类的对象,宏定义因为是文本替换,不可以

不适合使用内联函数的情况:

  1. 当inline内出现for,while时,函数的运行时间就比函数调用时间多出很多,那么使用inline的效率就很低,相反需要付出内存空间。
  2. inline不能使用递归。
  3. 函数体比较长,会消耗大量内存空间。
  4. 构造函数和析构函数不适合作为内联函数使用,因为编译阶段编译器会往构造和析构函数中额外加很多代码,比如申请/释放内存,初始化成员对象等等,可能代码并不精简。

3、Lambda

lambda表达式在其所在的位置上定义了一个匿名函数对象。
lambda表达式的形式:

[捕获值列表] (函数参数) mutable / exception -> 返回值类型

捕获值列表:分为值捕获,引用捕获。捕获的参数是我们能直接在函数体中使用的参数。和一般的函数不同的是,值捕获的值是在lambda创建时捕获的,也就是说在lambda创建后再改变值不会改变lambda内的捕获的值。

//example1
int a = 1;
auto fun = [a](){ return a; };
a = 11;
std::cout << fun();	//1

//example2
int a = 1;
auto fun = [&a](){ return a; };
a = 11;
std::cout << fun();	//11

函数参数:表示匿名函数的参数。
返回值类型:return的类型,void可以忽略。
函数体:函数的主体。

参考资料:

谈谈 C/C++ 中的 volatile
C++之Lambda表达式

posted @ 2020-05-05 22:32  KirinSB  阅读(153)  评论(0编辑  收藏  举报