目录
- C++ 记录
- 不要 混用带符号类型和无符号类型.主要是比较 加减.
- 右值引用.TODO
- 数组指针和指针数组
- const
- typedef
- auto
- decltype TODO
C++ 记录
不要 混用带符号类型和无符号类型.主要是比较 加减.
右值引用.TODO
数组指针和指针数组
a.数组指针: 是指针,指向数组. 如:
// 声明方式. 由于"[]"比"*"优先级要高,所以需要"()"
int (*parr)[5];
// 使用方式
int a[] = {1,2,3,4,5};
parr = &a;
// 打印
auto len = sizeof(a)/sizeof(a[0]);
for(int i = 0;i < len; ++i){
cout << (*parr)[i] << endl;
}
b.指针数组:是数组,里面存的指针.如:
// a是一个包含10个元素的数组,每个元素都是一个指向int类型的指针.
int* a[10];
const
引用不是一个对象.所以没有指向引用的指针.
如何区分顶层const 和 底层const?
指针如果添加const修饰符,有两种情况:
// 1. 指向int常量的指针
const int *a;
// 2. 指向int的指针常量
int *const b;
情况1叫 常量指针.
被指向的是一个常量,const修饰的是被指向的对象.但是指针本身(a)不是一个常量.可以指向其他变量.
即
int num = 10;
int val = 20;
const int *a = #
// *a = 20; // 错误. 不能通过 *a 去改变num的值
num = 11; // 正确
a = &val; // 正确
情况2叫 指针常量. 指针是一个常量.const修饰的是指针本身.所以指针本身不能改变,但是被指向的对象可以改变.
int num = 10;
int val = 20;
int *const a = #
a* = 11; // 正确
// a = &val; // 错误
顶层 const: 对于指针来说,修饰指针本身的const 就是 顶层const,修饰被指向的对象,是底层const.
如:
int * const a; // const修饰的是指针本身,顶层const
const int *a; // const修饰的是被指向的对象, 底层const
更一般的,顶层const可以表示任意的对象是常量,这一点对任何数据类型都适用,如算术类型、类、指针等.
底层const则与指针和引用等复合类型的基本类型部分有关.
比较特殊的是,指针类型既可以是顶层const,也可以是底层const,这一点和其他类型相比区别明显.
用于声明引用的 const 都是底层 const.
int i = 0;
int *const pi = &i; // 顶层 const
const int ci = 42; // 顶层 const
const int *p2 = &i; // 底层 const
const int &r = ci; // 用于声明引用的 const 都是底层 const
typedef
typedef char *pstring;
const pstring cstr; // const修饰的是 指针
不能理解成 const char *cstr;
复杂声明的理解规则: 右左法则
从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;
括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直到整个声明分析完。
如:
int (*func[5])(int *);
func是一个包含5个元素的数组,数组元素是 一个以int为返回值,参数为int指针的函数.
auto
a. auto 会忽略掉顶层 const, 保留底层 const;
如:
int num = 10;
const int *a = #
auto b = a;
// *b = 111; 错误, b相当于 const int* b;
const int cnum = 11;
auto c = cnum; // 顶层const被忽略,相当于 int
c = 12; // 正确
b.如果希望推断出的auto类型是一个顶层const,则需要明确指出:
int num = 10;
const auto p = #
int val = 11;
// p = &val; 错误, p中的const是一个顶层const
c. auto &
const int ci = 10;
auto & b = ci;
// b = 11; 错误, b是对ci的引用,就是ci的别名.
decltype TODO
decltype((var)); 双层括号的结果永远是引用.