引用不是对象,指针是对象
初始化空指针的方法:赋值为nullptr(推荐),null,0
字面值包括算术类型、指针、引用和某些类
类型别名:typedef double wages;//wages是double的同义词
c++11标准,使用using别名声明,using wages=double;
#pragma once也可以防止同一个文件被include多次,但是可移植性差,有些编译器不支持。
string、vector、迭代器、数组
(1)string字符串,cin读取遇到空白就停止,getline读取一整行遇到换行停止(允许有空格)
(2)string/vector.size()返回的不是int,是size_type类型,所以需要用decltype,例如:for(decltype (vector.size()) i=0;i<vector.size();i++)
(3)vector添加元素 puah_back()
(4)迭代器的类型为iterator和const_iterator 。常量只能用const_iterator,能读取不能修改所指的元素 如果只需读无须写最好用const_iterator
(5)c++11新标准中引入了cbegin和cend,不论是否是常量都返回const_iterator
(6)end指向尾元素的下一个位置,是一个不存在的元素位置,如果需要对迭代器赋空值或取空值,需要使用end()。
(7)end-begin的结果是他们之间的距离也就是相差的元素数,加减整数就相当于移动了该距离
下图是计算一组数字中首尾两数之和,从两端一直计算到中间的数字
(8)在使用数组下标的时候,通常将其定义为size_t类型,这是一个无符号(unsigned)类型,定义在cstddef头文件中。例如:unsigned num;这样num才能和数组下标一起计算。
下题是一个除法程序,展示try,catch的简单用法:
int a, b;
int num;
try{
cout << "请输入被除数和除数" << endl;
cin >> a >> b;
if (b == 0){
throw runtime_error("除数不能为0");
}
num = a / b;
cout << "结果是" << num;
}
catch(runtime_error err){
cout << err.what()
<< "请重新输入除数";
cin >> b;
num = a / b;
cout << "结果是" << num;
}
(9)有迭代器begin()和end()的类,可以使用范围for循环
例:for(auto &value : array)
函数
(1)如果函数不需要修改参数的值,最好把形参设为const
(2)函数列表初始化返回值
vector<string> process(){ return{"abc","bcd"}; }
返回一个vector对象存放string
(3)如果返回值类型比较复杂,可以使用C++11中的尾置返回
例如:auto func(int i) ->int(*)[10]; 表示返回指向一个含有10个整数的数组的指针
(4)允许main没有return语句,编译器会隐式地插入一条return 0
(5)顶层const不算是一种新的形参,无法满足函数重载
(6)const_cast
(7)默认实参,例如:
一旦某个形参有了默认值,则他后面的所有形参都必须有默认值
(8)内联函数在返回值前加inline,适合规模较小频繁调用的函数
(9)constexpr
constexpr函数是能用于常量表达式的函数,必须有且只有一个return,不强制变量和返回值是常量表达式,但是不是的话就不可以用于常量表达式
constexpr函数,被隐式地定义为内联函数
(10)assert
![]()
函数指针
类
(1)和数组类似,不能直接返回函数,但是可以返回指向函数的指针。
(2)成员函数的声明需要在函数内部,定义可以在内部也可以在外部。
(3)类的成员函数后面加const,表示这个函数不会修改这个类的数据成员,在常量成员函数中加mutable修饰的变量允许被修改,构造函数不能被声明为const。
const对象只能调用const成员函数(const对象例如:const Student lisi(),lisi是一个const对象),const对象的数据不能被修改。
(4)struct和class的区别:class的成员默认是private,struct默认public
class的继承默认是private,struct默认是public
class可以用在模板参数中,struct不能
(5)IO类不能拷贝,只能引用
(6)this是一个const指针,只能用在成员函数,指向当前对象,所以可以用*this代表当前对象this 是一个指针,要用->来访问成员变量或成员函数。
构造函数初始化列表,负责为新创建的对象的数据成员赋初值,在冒号和花括号之间
(7)友元补充
(8)如果成员是const、引用,未提供默认构造函数的类类型,必须通过构造函数初始化列表的方式提供初值,不能先初始化再赋值。
(9)委托构造函数
(10)隐式的类类型转换 ,如果构造函数支持调用一个实参,那么就可以使用该实参隐式转换为类类型,只允许一步类类型转换,隐式类类型转换可能会破坏程序可读性。
(11)explicit关键字声明构造函数可以阻止这种行为,这种函数只能直接初始化,不可以赋值的方式初始化
(12)字面值类
(13)static静态成员声明在类内,定义在类外,所有对象能共享。static函数与类关联不与对象关联,所以不包含this指针,不能定于为const函数。
(14) 在类中初始化vector成员变量
vector<string> str(5);
vector<int> s(5,0);
//两种方式都会报错
//C++11之后正确的方式为:
vector<string> name = vector<string>(5);
vector<int> val{vector<int>(5,0)};
IO类
(1)不能拷贝或者对流对象赋值,因此也不能将形参和返回值类型设置为流,需要用引用的形式,同时也不能设置为const。
(2)iostate的类型是位集合,对应流的当前状态。
(3)cin.ignore(a,ch)清除缓冲区中的数据,有两个参数数值型a,和字符型ch。常用来清除以回车结束的输入缓冲区的内容,消除上一次输入对下一次输入的影响,例如cin.ignore(100,'\n'),表示在读取100个字符或遇到回车后清除缓冲区。默认参数是cin.ignore(1,eof)把eof前的一个字符删掉。
(4)endl刷新缓冲区输出一个\n,ends刷新缓冲区输出一个空字符,flush刷新缓冲区不输出额外的字符。
(5)通过设置unitbuf可以控制是否需要缓冲区,cout<<unitbuf表示输出后立即刷新缓冲区。
(6)程序崩溃不会刷新缓冲区
(7)每个流最多关联到一个流,但多个流可以同时关联到一个流。输入流被关联到输出流后,任何输入操作之前都会刷新缓冲区。cin和cout是默认关联的。
(8)tie函数有两个重载的版本,不带参数的返回指向输出流的指针(如果关联到一个输出流,就返回这个输出流的指针,如果没有关联,就返回空指针),第二个版本接受一个指向输出流的指针,将自己关联到此输出流。
(9)将字符串输入到缓冲区时会将结尾的换行一起输入进去。
cin从缓冲区读取数据,遇到空字符就结束读取,并写入空字符前的数据,但是空字符还存在于缓冲区中。cin.getline()默认遇到换行符作为读取结束的标志,并清除掉这个标志,也可以自己设置结束读取的标志,需要指定读取的字符的数量。
getline()是一个全局函数,用来处理string,在读取时遇到三种情况会停止:文件结束、遇到换行、输入达到上限。函数的定义为:
delim是终结符,遇到该字符停止读取操作,不写的话默认为换行符。与cin.getline()相同,遇到终结符时会停止读取并且输入缓冲区中这个终结符也没有了。
顺序容器
(1)顺序容器之间拷贝如果元素类型不同,不能直接拷贝,可以使用迭代器范围拷贝。
动态内存
allocator类
class Example { public: Example() : a(0) { cout << "example default constructor..." << endl; } Example(int x) : a(x) { cout << "example constructor..." << endl; } ~Example() { cout << "example destructor..." << endl; } int a; }; int main() { allocator<Example> alloc; Example *p = alloc.allocate(2); alloc.construct(p); alloc.construct(p + 1, 3); cout << p->a << endl; cout << (p + 1)->a << endl; alloc.destroy(p); alloc.destroy(p + 1); alloc.deallocate(p, 2); }
输出如下:
example default constructor... example constructor... 0 3 example destructor... example destructor...