1、带符号类型和无符号类型同时出现在表达式中时,带符号类型会自动转换为无符号类型。
int a = -1;
unsigned b = 1;
cout << a*b << endl;
我的环境里输出为:4294967295
2、字符和字符串字面值
'a' 字符字面值,"hello world" 字符串字面值。
字符串字面值的类型实际上是由常量字符构成的数组,编译器在每个字符串的结尾添加一个空字符('\0'),因此字符串字面值的长度要比实际内容多1。如:'A'表示单独的字符A,而 "A" 则代表了一个字符的数组,该数组包含两个字符:A和空字符。
cout << sizeof('a') << endl; //1
cout << sizeof("a") << endl;//2
3、初始化
c++中初始化和赋值时两个完全不同的操作。即使有时候这种区别无关紧要,但初始化并不是赋值的一种。初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除而以一个新值来代替。
以下4条语句都可以初始化一个int
int a = 0;
int a = { 0 };
int a(0);
int a{ 0 };//c++11新标准
第四种用花括号的初始化的形式称为列表初始化,这种初始化用于内置类型的变量时有个重要特点:如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器将会报错:
long double ld = 3.1415926536;
int a{ ld }, b{ ld }; //错误,转换未执行,存在丢失信息的风险
int c(ld), d(ld); // 正确,转换执行,且确实丢失部分值
4、初始化和对const的引用
引用的类型必须与其引用对象的类型一致,但也有例外:在初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。
int i = 1;
const int &r1 = i;//正确
const int &r2 = 1;//正确,r2是一个常量引用
const int &r3 = r1 * 2;//正确
int &r4 = r1;//错误, r4不是常量引用
double d = 3.14;
int &r5 = d; //错误 类型不匹配
const int &r6 = d;//正确
//r6的初始化相当于
const int tmp = d;
const int &r6 = tmp;
5、类型别名
看下面的声明
typedef char* pstring;
const pstring cstr = 0; //cstr是指向char的常量指针
const char* cstr2 = 0; //cstr2是指向const char的指针
遇到一条使用了类型别名的声明语句时,人们往往回错误的尝试把类型别名替换成它本来的样子,以理解该语句的含义。这种理解时错误的。声明语句中用到pstring时,其基本数据类型是指针,char*重写后,基本数据类型变成了char,*成了声明符的一部分。
6、decltype和引用
int i = 10, *p = &i, &r = i;
decltype(r + 0) b; //正确 加法的结果是int 因此b是一个未初始化的int
decltype(*p) c; //错误 c是int&, 必须初始化
//decltype的表达式如果是加上了括号的变量,结果将是引用
decltype((i)) d; //错误 d是int& 必须初始化
decltype(i) e; //正确 e是一个未初始化的int
decltype((variable)) (注意是双层括号)的结果永远是引用,而decltype(variable)的结果只有当variable本身就是一个引用时才是引用。