最近打算看STL源码剖析,但是自感C++语法不精,还是从《C++Primer》补起,两年前看过的书,现在再看,又是另一番感觉了。
类型
- 指定类型:
前缀 | 类型 |
---|---|
u | (unicode16)char16_t |
U | (unicode32)char32_t |
L | wchar_t |
u8 | (utf8)char |
后缀 | 类型 |
---|---|
u/U | unsigned |
l/LL | long |
ll/LL | long long |
f/F | float |
l/L | long double |
- C++区分声明和定义:声明使得名字为程序所知,定义在此之上分配空间。
- 仅声明一个变量:extern int i;
- 一旦声明显式初始化则视为定义:extern int i=1;
- using,typedef功能相似
- 定义于函数体外的变量被初始化为0。【包括类成员】P40
- 显式访问局部变量: ::global
- 引用:不占空间,由此引发与指针的诸多不同,个人猜测在汇编阶段就是一个标记符。
- 不能定义引用的引用。
- 指针:不能定义指向引用的指针;推荐用nullptr;int* p1,p2;p1指针,p2int,的作用范围仅为最近的一个变量;int *p;int &r=p;r为对指针p的引用。
const:
默认下const对象仅在本文件有效,于其他文件的同名对象而言实际上是不同的变量。当需要使用全局跨文件的变量,声明和定义都加上extern即可:
//file.cpp
extern const int i=1;
//file.h
extern const int i;const+引用=该引用只读。
const的对象只能由const引用来引用:
const int i=2;
const int &j=i; //对
int &k=i; //错
允许为一个const引用绑定到非常量,字面值或者一般表达式。因为在实现的时候,上述值是保存在编译器提供的临时变量,与原变量没有任何关联,即使修改了也达不到通过引用修改值的目的,所以干脆const掉。详见P55- const+指针=顶层const/底层const
- 顶层const:变量本身是常量,指针本身是常量,不能改指向
int i=0,j=0;
int *const p1=&i;
p1=&j; //错 - 底层const:指针指向的对象是常量
const int h=0;
const int *p2=&h;
在涉及指针的copy的时候,底层const仅能赋值给底层const,而不能赋值给其他非底层const。【出于保证底层const指向的对象不被修改】P58
- 顶层const:变量本身是常量,指针本身是常量,不能改指向
常量表达式:在编译过程就能得到计算结果的表达式。
const int s=get(); //错,因为需要在运行时才知道s的值
constexpr:P66声明为constexpr的变量一定是常量,而且必须用常量表达式初始化:
constexpr int sz=size() //iff size()是一个constexpr函数时正确
constexpr+指针=顶层const- auto+引用/指针/常量 P62
- decltype():自动推断式子中的类型并作为声明类型
- size_type:string的返回类型,与机器相关的无符号,被设计的足够大来表示内存中任意对象的大小。
- 范围for: for(auto c:s)//只读
for(auto &c:s)//可写 - 类模版不能以引用为类型
- 范围for内不应修改遍历序列的大小,因为遍历终点被预先保存下来。
- 迭代器类型:iterator/const_iterator 可读写/只读
凡是用了迭代器的循环体,都不能添加元素
运算符
- ->=(*p). 箭头运算符将解引用和成员运算结合在一起
- 复杂的数组声明:
int (*p)[10]=&arr;//p指向有10个int的数组
int (&q)[10]=arr;//q引用有10个int的数组
从内到外阅读。P103
关于auto 和decltype对数组的类型推断P105 - 用范围for处理多为数组,除了最内层,所有层的循环的控制变量都应该是引用类型
for(const auto &row:ia)
for(auto col:row) - 对于未定义运算顺序的表达式结果不可控:
cout<<i<<" "<<++i<<endl;
定义了运算顺序的只有&&,||,?:和,四种运算符
f()+g()*k()-h(),四个函数调用顺序完全未定义
while(beg!=s.end()&&isspace(*beg))
*beg=toupper(*beg++) //错,因为未定义运算顺序,一条子表达式(*beg++)修改了某个对象的值,而另一条子表达式又要用该值(*beg=)这种行为的运算顺序未定义
- 强调使用++i,尤其是迭代器
- 符号位的处理未定义,所以仅将位运算用于无符号数