short 16位 long 32位 long long 64位(c++11新定义)
wchar_t 用于确保可以存放机器最大扩展字符集中任意一个字符
char16_t char32_t 为Unicode服务
除bool型和扩展的字符型以外,其他整形可以划分为带符号的和无符号的
字符型被分为 char/signed char/unsigned char,尽管字符型有三种,但是字符表现形式只有两种 signed 和 unsigned ,char会表现为上述两种中的一种,由编译器决定
在算数表达式中不要使用char或bool,如果一定要使用char ,指明 signed or unsigned
执行浮点数运算用double: float 精度通常不够,double 与 float 运行时间相差无几,但是long double的运行时间不容忽视
非bool 转为bool 0->true 非0->false
bool转为非bool false->0 true->1
浮点转整数仅保留浮点数小数点之前部分
整数转浮点,小数部分记为0,如果整数所占空间超过浮点类型容量,可能损失精度
赋给无符号类型一个超出其范围的值,结果是初始值对该类型表示数值总数取模后的余数
赋给给带符号类型一个超出其范围的值,结果是未定义的
切勿混用带符号类型和无符号类型,因为带符号数会自动转化为无符号数
一个形如42的值被称作字面值常量,每个字面值常量对应一个数据类型,字面值常量的形式和值决定了它的数据类型
整形和浮点型:
以0开头表示8进制数,以0x or OX开头代表16进制
eg 20=024=0x14
十进制字面值是带符号数,是int/long/long long中能容纳的最小的一个
8进制 16进制是 int / unsigned int / long / unsigned long / long long / unsigned long long 中最小的
如果一个字面值连与之关联的最大数据类型都放不下,会引发错误
short没有对应的字面值
严格的讲,十进制字面值不是负数,符号的作用是对字面值取负值
浮点型表示为一个小数或科学计数法表示的指数,指数部分用e或E
eg: 3.14 3.14E0 0. 0e0 .001
默认为double
字符和字符串
编译器在每个字符串结尾添加一个'/0',因此字符串字面值实际长度比内容多1
书写的字符串字面值比较长,可以分开书写
std::cout <<"a really, really long string interal"
"that spans two lines" << std::endl;
转义序列
换行符 \n 横向制表符 \t 报警符 \a 纵向制表符 \v 退格符 \b 双引号 \" 反斜线 \\ 问号 \? 单引号 \' 回车符 \r 进纸符\f
指定字面值的类型
L'a'//宽字符型字面值,类型 wchar_t
u8"hi!"//utf-8字符串字面值
42ULL//无符号整形字面值,unsigned long long
1E-3F//单精度浮点字面值 float
3.14159L//long double
长整形字面值用大写L 小写l和1易混
字符和字符串字面值
前缀 含义 类型
u unicode 16 char16_t
U unicode 32 char32_t
L 宽字符 wchar_t
u8 UTF-8 char
整形字面值
后缀 最小匹配类型
u or U unsigned
l or L long
ll or LL long long
浮点型字面值
f or F float
l or L long double
布尔字面值和指针字面值
true/false 是bool类型字面值
nullptr 是指针字面值
初始化不等于赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值替代
定义一个名为sold的int变量并初始化为0:
int sold=0;
int sold={0};
int sold{0};
int sold(0);
c++11标准用花括号来初始化变量得到全面应用,这种初始化方法叫列表初始化
如果使用列表初始化且初始值存在丢失信息的风险:
long double ld=3.14;
int a{ld},b={ld}; //错误,转换未执行,因为存在丢失信息风险
int c(ld),d=ld; //正确,转换执行,且确实丢失了部分值
3.2.1 3.3.1对列表初始化有更多介绍
定义于任何函数体之外的变量被初始化为0,定义在函数体内部的内置类型变量不被初始化,一个为被初始化的内置类型变量的值是未被定义的
每个类各自决定其初始化对象的方式,而且是否允许不经初始化就定义对象也由类自己决定(如不允许,如果创建但未初始化则引发错误)
绝大多数类都支持无需显示初始化而定义对象,如string生成一个空串
分离式编译:允许将程序分割成若干个文件,每个文件可被独立编译
为了支持分离式编译,c++将声明和定义区分开,声明(declaration)是的名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明,而定义(definition)负责创建于名字关联的实体
变量声明规定了变量的类型和名字,定义还申请储存空间,也可能为变量赋一个初始值
如果想声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显式初始化变量
extern int i; //声明i而非定义i
int j; //声明并定义j
任何包含了显式初始化的声明即成为定义。
extern double pi=3.14; //定义
在函数体内部,如果试图初始化一个由extern关键字标记的变量,将引发错误
变量只能被定义一次,但可以被多次声明
C++用户自定义标识符不能连续出现两个下划线,也不能以下划线紧连大写字母开头,定义在函数体外的标识符不能以下划线开头
变量名一般用小写字母,类名一般以大写字母开头,如果标识符由多个单词组成,应有明显区分
名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端为结束
全局作用域:定义于所有花括号之外,在整个程序范围内都可使用
块作用域:一部分可以使用
被嵌套的作用域称为内层作用域,嵌套别的作用域的称为外层作用域
允许内层作用域重新定义外层作用域已有名字,但不宜定义
#include
int reused=1;
int main()
{
std::cout << reused << std::endl; // 1
int reused=0;
std::cout << reused << std::endl; //0
std::cout << ::reused<< std::endl; //1 显式访问全区变量reused
return 0;
}
c++11增添右值引用(13.6.1),主要用于内置类,在使用术语"引用(reference)"时,实际指左值引用
引用为对象起了另外一个名字,将声明符写成&d来定义引用类型
int ival=1024;
int &refVal=ival; //refVal指向ival(是ival的另一个名字)
int &refVal2;//错误:引用必须初始化
引用并非对象,只是为已经存在的对象所起的另一个名字,定义了一个引用后,对其进行的所有操作都是在与之绑定的对象上进行的。
因为引用并非对象,所以不能定义引用的引用
允许一条语句定义多条引用,每个引用标识符必须以&开头
除了2.4.1与15.2.3介绍的两种例外情况,其他所有引用的类型必须和与之绑定的对象严格匹配,而且引用只能绑定在对象上,不能与字面值或某个表达式的计算结果绑定在一起。
指针(pointer)是只想另一种类型的复合类型,与引用相似而又不同(1)指针本身是对象,允许对指针赋值和拷贝,也可以指向不同对象(2)无需定义时赋初值
int val=42;
int *p=&val;//p存放的是ival的地址,或者说p是指向变量ival的指针
因为引用不是对象,不能定义指向引用的指针,除2.4.2 15.2.3两种特殊情况,类型要严格匹配
int val=42;
int *p=&val;
cout<<*p; //输出42
对指针解引用会得出所指的对象,如果给解引用结果赋值,就相当于给指针所指对象赋值
*p=0;
cout << *p //输出0
int *p1=nullptr;//c++11标准
int *p2=0;//需include
int *p3=NULL;
int i=42;
int *p1=&i; //pi被初始化,存有i的地址
int *p2=nullptr;
p2=&i; //p2指向i
*p2=1; //i的值变成1,p2未改变
int ival=1024;
int *pi=&ival; //pi指向一个int 型的数
int **ppi=π//ppi指向一个int型指针
const常量一旦创建后其值就不能再改变,所以const常量必须初始化,初始化可以是任意复杂表达式
默认状态下,const对象仅在文件内有效,多个文件中出现同名const变量,等同于在不同文件中分别定义了独立的变量
如果不是常量表达式,并需要在文件间共享,即在一个文件中定义const,而在其他多个文件中声明并使用:
不管是声明还是定义都添加extern关键字,定义中extern表示可被其他文件使用,声明中extern表示它的定义将在别处出现
//file_1.cc定义并初始化一个常量,该常量能被其他文件访问
extern const int bufSize=fcn();
//file_1.h头文件与file_1.cc中定义的bufSize是同一个
extern const int bufSize
const int ci=1024;
const int &r1=ci;
r1=42;//错误:r1是对常量引用,不能修改
int &r2=ci;//错误:试图让一个非常量引用指向一个常量对象
引用的类型必须和所引用的对象一致,例外情况 初始化常量引用时时可以用任意表达式作为初始值,只要该表达式结果能转换成引用的类型,允许一个常量引用绑定非常量的对象。
常量引用的的实质:
double dval=3.14;
const int &r1=dval;
//等价于
const int temp=dval;
const int &ri=temp;
但是初始化非常量引用时不允许如此。
对const的引用可以引用一个非const对象
const double pi=3.14; //pi是一个常量
double *ptr=π //错误,不能用非常量指针指向常量
const double *cptr=π //正确
*cptr=42; //错误,不能给cptr赋值
double dval=3.14;//dval是个双精度浮点数
cptr=&dval;//正确,但是不能通过cptr改变dval的值
int e=0;
int *const cur=&e;//cur将一直指向e
const double pi=3.14;
const double *const pip=π //pip是一个指向常量对象的常量指针
const int max_files=20; //max_files是常量表达式
const int limit=max_files+1;//limit是常量表达式
int staff_size=27; //staff_size不是常量表达式,数据类型是int
const int sz=get_size();//sz不是常量表达式,具体值运行时才能获取
constexpr int mf=20;//20是常量表达式
constexpr int limit = mf + 1; //mf+1是常量表达式
constexpr int sz = size(); //size是一个constexpr函数时是一个正确声明语句
6.5.2介绍允许定义constexpr函数
constexpr int *np = nullptr; // np是一个指向整数的常量指针,其值为空
int j = 0;
constexpr int i = 42; //i是整形常量
constexpr const int *p = &i; //p是常量指针,指向整形常量
constexpr int *p1 = &j; //p1是常量指针,指向j
typedef double wages; //wages是double的同义词
typedef wages base , *p //base是double的同义词,p是double*的同义词
using SI Sales_item; // SI是Sales_item 的同义词
类型别名和类型的名字等价
typedef char *pstring;
const pstring cstr = 0; //cstr是指向char的常量指针
const pstring *ps; //ps是一个指针,他的对象是指向char的常量指针
上述两条声明语句的基本数据类型都是const pstring,和过去一样,const是对给定类型的修饰。 pstring实际上是指向char的指针,因此,const pstring是指向char的常量指针
const char *cstr = 0; //错误理解
声明语句中用到pstring,其基本数据类型是指针,可是用char*重写了声明语句后,数据类型就变成了char ,*成了声明符的一部分,这样改写的结果是,const char成了基本数据类型。
auto item = val1 + val2; //item初始化为val1和val2相加的结果
使用auto语句也能在一条语句中声明多个变量,因为一条声明语句只能有一个基本数据类型,所以该语句中所所有变量的出事基本数据类型必须一样
auto i = 0, *p = &i; //正确 i是整数,p是整形指针
auto sz = 0, pi = 3.14; //错误 sz和pi类型不一致
int i = 0, &r = i;
auto a = r; //a是一个整数
auto一般会忽略顶层const,而底层const被保留下来
const int ci = i ,&cr = ci;
auto b = ci; //b是一个整数(ci的顶层const被忽略)
auto c = cr; //c是一个整数(cr是ci的别名,ci本身是一个顶层const)
auto d = &i; //d是一个整形指针(整数的地址就是指向整数的指针)
auto e = &ci; //e是一个指向整数常量的指针(对常量取地址是底层const)
如果希望推断出的auto类型是一个顶层const,需明确指出:
const auto f = ci; //f是const int
auto &g = ci; //g是一个整形常量引用,绑定到ci
auto &h = 42; //错误 不能为非常量引用绑定字面值
const auto &j = 42; //正确,可以为常量引用绑定字面值
decltype(f()) sum = x; // sum的类型是函数f的返回类型
编译器并不实际调用函数f
const int ci = 0, &cj = ci;
decltype(ci) x = 0; //x的类型是 const int
decltype(cj) y = x; //y的类型是 const int&,y绑定到变量x
decltype(cj) z; //错误 z是一个引用,必须初始化
引用从来都作为其所指对象的同义词出现,只用用在decltype处是个例外
//decltype的结果可以是引用类型
int i = 42, *p = &i, &r = i;
decltype(r+0) b; //正确,b是一个未初始化的int
decltype(*p) c; //错误,c是int&,必须初始化
因为r是一个引用,decltype(r)是引用,让结果类型是r所指的类型,可以把r作为表达式的一部分,如r+0
decltype((i)) d; //错误:d是引用,必须初始化
decltype(i) e; //正确,e是一个int
struct Sales_data
{
std::string boolNol
unsigned units_sold = 0;
double revenue = 0.0;
};
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include
struct Sales_data
{
std::String boolNo;
};
#endif
预处理变量无视c++语言中关于作用域的规则