10.无符号数不会小于0
注意不能将带符号类型和无符号类型混合使用。
11.变量声明与定义的关系
extern int i;//声明i而非定义i(只声明不定义用extern)
int j;//声明并定义j
extern int i=1;//定义(赋值操作抵消了extern的作用,任何包含了显示初始化的声明即为定义)
在函数体内部初始化一个extern关键字标记的变量,将引发错误。
变量能且仅能被定义一次,但可多次声明;若在多个文件中使用同一变量,就必须将声明(用到的文件中)与定义(只能出现在一个文件中)分离。
12.约定俗成的标识符命名规范
标识符要能体现实际含义
变量名一般用小写字母
用户自定义的类名一般以大写字母开头
如果标识符由多个单词组成,则单词间应该有明显的区分。student_loan或studentLoan.
13.建议在第一次使用变量时再定义它。有助于找到变量的定义,并且当定义与第一次使用的地方很近时,方便赋给它一个合理的初始值
若函数有可能用到某全局变量,则不宜再定义一个同名的局部变量。
14.引用
引用并非对象。它只是为一个已经存在的对象所起的另外一个名字。
int ival=1024;
int &refVal=ival;//refVal是ival的另一个名字
引用必须初始化,一旦初始化完成,引用将与它的初始值(必须是一个对象,而不是常量)一直绑定在一起,无法令引用再绑定到另外的变量。不能再定义引用的引用。
14.建议初始化所有指针
void*是一种特殊的指针类型,可以用于存放任意对象的地址,对该地址中到底是什么类型的对象并不了解
double obj=3.14;
void* p=&obj;//ok
int* p1,p2;//p1是指针,p2是int
int *p1,*p2;//ok
引用指针不是一个对象,所以不能定义指向引用的指针。
但指针是对象,所以存在对指针的引用。int *p;int *&r=p;
面对一条比较复杂的指针或引用的声明语句时,从右向左阅读有助于弄清楚它的真实含义。
15.只在一个文件中定义const,而在其他多个文件中声明并使用它: 对于const常量无论是声明还是定义(必须的)都添加extern关键字,这样只需定义一次就可以。
16.常量引用是对const的引用
引用的对象是常量还是非常量可以决定其所能参加的操作,却无论如何不会影响到引用和对象的绑定关系本身。
对常量的引用不能被用作修改它所绑定的的对象。
初始化常量引用时允许用任意表达式作为初始值。
int i=2;
const int &r=i;//ok
const int &r1=2;//ok
const int &r2=r1*2;//ok
int &r3=r1*2;//error,常量引用的值不允许赋给非常量引用
17.constexpr关键字
如果认定变量是一个常量表达式,就把它声明为constexp类型
constexp int mf=20;//20是常量表达式
constexp ing limit=mf+1;//mf+1是常量表达式
18.auto类型说明符
分析表达式所属的类型,通过初始值来推算变量的类型。
auto item=val1+val2;//item初始化为val1+val2的结果
auto sz=0,pi=3.14;//error,一条声明语句只能有一个基本类型
19.decltype类型指示符
decltype选择并返回操作数的数据类型。编译器分析表达式并得到它的类型,却不实际计算表达式的值。
decltype(f()) sum=x;//编译器并不实际调用函数f,而是使用当调用发生时f的返回值类型作为sum的类型。
引用从来都作为其所指对象的同义词出现,只有用在decltype处是一个例外
decltype和引用 P63
20.头文件
头文件通常包含制备定义一次的实体,如类、const、和constexpr变量
头文件一旦改变,相关的源文件必须重新编译以获取更新过的声明
头文件保护符:使用预处理变量头防止重复包含的发生。
#ifndef 头文件名
#define 头文件名
//头文件内容
#endif
21.命名空间的using声明
eg: using namespace::std;
注意头文件不应包含using声明,因为头文件的内容会被拷贝到所有引用它的文件中去,如果头文件使用了某个using声明,会导致每个使用了该头文件的文件都会有这个声明,易产生名字冲突。
22.string类型[可变长的字符序列]
使用时需要
#include <string.h>
using namespace::string;
初始化: string s3("xxx");//直接初始化,s3是字面值xxx的副本
string s3="xxx";//拷贝初始化,s3是字面值xxx的副本
string s4(10,'c');//,直接初始化,s4的内容是cccccccccc
string s1=string(10,'c');//拷贝初始化,s1的内容是cccccccccc
string s2(s1);//s2是s1的副本,等价于string s2=s1;
string对象s的操作:
s.empty();//返回值bool
s.size();//返回一个无符号的size_type类型的值,所以不要和有符号的值混用,所以表达式中有size()函数就不要再用int了
//允许编译器通过auto和decltype来推断变量类型auto len=word.size();
s[n];//s[0]是第一个字符,以此类推...
s1+s2;//可以两个对象s1+=s2;
字面值相加s3=s1+","+s2;//当把string对象和字符字面值及字符串混在一条语句中使用时,
//必须确保每个+[注意是每个+]的两侧的运算对象至少有一个是string,
//注意c++中的字符串面值与string并不是同一个类型
s1=s2;s1==s2;s1!=s2;<,<=,>,>=//对大小写敏感
cin>>s;cout<<s;//输入输出,说明:在执行读取操作是string对象会自动忽略开头的空白(空格/换行/制表符),
并从第一个真正的字符开始读起,直到遇见下一处空白为止。
cin>>s1>>s2;多个对象可连结
读入未知数量的string对象:string word;
while(cin>>word){...}//未遇到结束标记或非法输入
用getline替换cin中的>>,可以保留输入时的空白符,换行符触发getline函数返回后被丢弃
while(getline(cin,word)){...}
范围for语句
for(declaration:excepression)
statement
eg:string str("some string")
for(auto c:str)//对于str中的每个字符
cout<<c<<endl;每行输出一个字符
注:在访问指定字符前,要检查string类型是否为空if(s.empty()){...}
23.建议使用cname的头文件而不使用name.h的头文件,标准库中的名字总能在命名空间std中找到,而后者程序员需要牢记那些是从c继承的,哪些是c++独有的
24.向量Vector
24.1基本操作
定义:vector<int> a(10);
vector<int> a(10,1); //10个整数元素的向量,且每个元素的初值为1,(数组只能通过循环来成批的赋给相同的值)
vector<int> c(b);
vector<int> d(b.begin(),b.begin()+3);//定义了其值依次为b向量中第0到第2(共3个)元素的向量
b.begin()/b.end()分别表示b的起始元素位置/最后一个元素之外的元素位置【注意是位置,不是值】
b.front()/b.back()表示b的第一个元素的值/最后一个元素值
b.size()表示b中元素的个数
b.clear()清空b中元素 b.empty()判断b是否为空
b.popback()删除b的最后一个元素 b.push_back(5)向b最后插入一个元素,其值为5
b.resize(10)将b的元素个数调至10个,多则删,少则补,其值随机
b.resize(10)将b的元素个数调至10个,多则删,少则补,其值为2