——修饰符类型

修饰符用于改变基本类型的含义,所以它更能满足各种情境的需求。

下面列出了数据类型修饰符:

  • signed
  • unsigned
  • long
  • short
修饰符 signed、unsigned、long 和 short 可应用于整型,signedunsigned 可应用于字符型,long 可应用于双精度型。
修饰符 signedunsigned 也可以作为 longshort 修饰符的前缀。例如:unsigned long int
C++ 允许使用速记符号来声明无符号短整数无符号长整数。您可以不写 int,只写单词 unsigned、shortunsigned、long在这里int 是隐含的。
//下面的两个语句都声明了 无符号整型变量
unsigned x;
unsigned int y;
	
short int i;          // 有符号短整数
short unsigned int j; // 无符号短整数


~类型限定符
类型限定符提供了变量的额外信息。
限定符 含义
const const 类型的对象在程序执行期间不能被修改改变。
volatile 修饰符 volatile 告诉编译器不需要优化volatile声明的变量,让程序可以直接从内存中读取变量。对于一般的变量编译器会对变量进行优化,将内存中的变量值放在寄存器中以加快读写效率。
restrict restrict 修饰的指针是唯一 一种访问它所指向的对象的方式。只有 C99 增加了新的类型限定符 restrict。


——存储类
存储类定义 C++ 程序中变量/函数的范围(可见性)和生命周期。这些说明符放置在它们所修饰的类型之前
  • auto
  • register
  • static
  • extern
  • mutable
  • thread_local (C++11)
( 从 C++ 11 开始,auto 关键字不再是 C++ 存储类说明符,且 register 关键字被弃用。)

~auto 存储类
自 C++ 11 以来,auto 关键字用于两种情况:1.声明变量时根据初始化表达式自动推断该变量的类型  2.声明函数时函数返回值的占位符。
(C++98标准中auto关键字用于自动变量的声明,但由于使用极少且多余,在C++11中已删除这一用法。)
//根据初始化表达式自动推断被声明的变量的类型,如:

auto f=3.14;      //double
auto s("hello");  //const char*
auto z = new auto(9); // int*
auto x1 = 5, x2 = 5.0, x3='r';//错误,必须是初始化为同一类型


~register 存储类
register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),😮且不能对它应用一元的 '&' 运算符(因为它没有内存位置)。
register int  miles;
寄存器只用于需要快速访问的变量,比如计数器。😮还应注意的是,定义 'register' 并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制。


~static 存储类
static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。
( 当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。😫在 C++ 中,当 static 用在类数据成员上时,会导致仅有一个该成员的副本被类的所有对象共享。)


~extern 存储类
extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。( 当您使用 'extern' 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。)
当您有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。
extern 修饰符通常用于当有两个或多个文件共享相同的全局变量或函数的时候,如下所示:

第一个文件:main.cpp
#include <iostream>
 
int count ;
extern void write_extern();
 
int main()
{
   count = 5;
   write_extern();
}

第二个文件:support.cpp
#include <iostream>
 
extern int count;
 
void write_extern(void)
{
   std::cout << "Count is " << count << std::endl;
}
它会产生下列结果:
Count is 5


~mutable 存储类
😫mutable 说明符仅适用于类的对象,它允许对象的成员替代常量。也就是说,mutable 成员可以通过 const 成员函数修改。


~thread_local 存储类
使用 thread_local 说明符声明的变量仅可在它在其上创建的线程上访问。 变量在创建线程时创建,并在销毁线程时销毁。 每个线程都有其自己的变量副本。
( thread_local 说明符可以与 static 或 extern 合并。可以将 thread_local 仅应用于数据声明和定义,thread_local 不能用于函数声明或定义。)

以下3类可以被声明为thread_local变量
  1. 命名空间下的全局变量
  2. 类的static成员变量
  3. 本地变量
以下演示了可以被声明为 thread_local 的变量:

thread_local int x;  // 命名空间下的全局变量
class X
{
    static thread_local std::string s; // 类的static成员变量
};
static thread_local std::string X::s;  // X::s 是需要定义的
 
void foo()
{
    thread_local std::vector<int> v;  // 本地变量
}



——运算符
运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C++ 提供了以下类型的运算符:
  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 位运算符
  • 赋值运算符
  • 杂项运算符
~算术运算符
运算符 描述
+ 把两个操作数相加
- 从第一个操作数中减去第二个操作数
* 把两个操作数相乘
/ 分子除以分母
% 取模运算符,整除后的余数
++ 自增运算符,整数值增加 1
-- 自减运算符,整数值减少 1

~关系运算符
运算符 描述
== 检查两个操作数的值是否相等,如果相等则条件为真。
!= 检查两个操作数的值是否相等,如果不相等则条件为真。
> 检查左操作数的值是否大于右操作数的值,如果是则条件为真。
< 检查左操作数的值是否小于右操作数的值,如果是则条件为真。
>= 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。

~逻辑运算符
运算符 描述
&& 逻辑与运算符。如果两个操作数都非零,则条件为真。
|| 逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。
! 逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。

~位运算符
运算符 描述
& 如果1同时存在于两个操作数中,二进制 AND 运算符复制一位到结果中。
| 如果1存在于任一操作数中,二进制 OR 运算符复制一位到结果中。
^ 如果存在于其中一个操作数中但不同时存在于两个操作数中,二进制异或运算符复制一位到结果中。
~ 二进制补码运算符是一元运算符,具有"翻转"位效果,即0变成1,1变成0。
<< 二进制左移运算符。左操作数的值向左移动右操作数指定的位数。
>> 二进制右移运算符。左操作数的值向右移动右操作数指定的位数。


~赋值运算符
运算符 描述
= 简单的赋值运算符,把右边操作数的值赋给左边操作数
+= 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数
-= 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数
*= 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数
/= 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数
%= 求模且赋值运算符,求两个操作数的模赋值给左边操作数
<<= 左移且赋值运算符
>>= 右移且赋值运算符
&= 按位与且赋值运算符
^= 按位异或且赋值运算符
|= 按位或且赋值运算符


~杂项运算符
运算符 描述
sizeof sizeof 运算符返回变量的大小。例如,sizeof(a) 将返回 4,其中 a 是整数。
Condition ? X : Y 条件运算符。如果 Condition 为真 ? 则值为 X : 否则值为 Y。
, 逗号运算符会顺序执行一系列运算。整个逗号表达式的值是以逗号分隔的列表中的最后一个表达式的值。
.(点)和 ->(箭头) 成员运算符用于引用类、结构和共用体的成员。
Cast 强制转换运算符把一种数据类型转换为另一种数据类型。例如,int(2.2000) 将返回 2。
& 指针运算符 & 返回变量的地址。例如 &a; 将给出变量的实际地址。
* 指针运算符 * 指向一个变量。例如,*var; 将指向变量 var。

~运算符优先级
类别 运算符 结合性
后缀 () [] -> . ++ - - 从左到右
一元 + - ! ~ ++ - - (type)* & sizeof 从右到左
乘除 * / % 从左到右
加减 + - 从左到右
移位 << >> 从左到右
关系 < <= > >= 从左到右
相等 == != 从左到右
位与 AND & 从左到右
位异或 XOR ^ 从左到右
位或 OR | 从左到右
逻辑与 AND && 从左到右
逻辑或 OR || 从左到右
条件 ?: 从右到左
赋值 = += -= *= /= %=>>= <<= &= ^= |= 从右到左
逗号 , 从左到右



——循环

~循环类型
循环类型 描述
while 循环 当给定条件为真时,重复语句或语句组。它会在执行循环主体之前测试条件。
for 循环 多次执行一个语句序列,简化管理循环变量的代码。
do...while 循环 除了它是在循环主体结尾测试条件外,其他与 while 语句类似。
嵌套循环 您可以在 while、for 或 do..while 循环内使用一个或多个循环。

~循环控制语句
控制语句 描述
break 语句 终止 loopswitch 语句,程序流将继续执行紧接着 loop 或 switch 的下一条语句。
continue 语句 引起循环跳过主体的剩余部分,立即重新开始测试条件。
goto 语句 将控制转移到被标记的语句。但是不建议在程序中使用 goto 语句。


~无限循环
如果条件永远不为假,则循环将变成无限循环。( for 循环在传统意义上可用于实现无限循环。由于构成循环的三个表达式中任何一个都不是必需的,您可以将某些条件表达式留空来构成一个无限循环。)

一般情况下,C++ 程序员偏向于使用 for(;;) 结构来表示一个无限循环。
注意:您可以按 Ctrl + C 键终止一个无限循环。



——判断

~判断语句
描述
if 语句 一个 if 语句 由一个布尔表达式后跟一个或多个语句组成。
if...else 语句 一个 if 语句 后可跟一个可选的 else 语句,else 语句在布尔表达式为假时执行。
嵌套 if 语句 您可以在一个 ifelse if 语句内使用另一个 ifelse if 语句。
switch 语句 一个 switch 语句允许测试一个变量等于多个值时的情况。
嵌套 switch 语句 您可以在一个 switch 语句内使用另一个 switch 语句。
? : 运算符
它的一般形式如下(Exp1、Exp2 和 Exp3 是表达式):
Exp1 ? Exp2 : Exp3;
? :表达式的值是由 Exp1 决定的。如果 Exp1 为,则计算 Exp2 的值,结果即为整个 ? :表达式的值。如果 Exp1 为,则计算 Exp3 的值,结果即为整个 ?: 表达式的值。