C++学习笔记
来源:互联网 发布:windows 扩展屏幕 ipad 编辑:程序博客网 时间:2024/06/09 14:30
- 第一章快速入门
- 输入和输出
- 操作符
- 命名空间
- 读取未知数目的输入
- 报错
- 类的简介
- 头文件
- 输入和输出
- 第二章变量和基本类型
- wchar_t
- 宽字符字符串
- 字符串连接
- 多行连接
- 初始化
- 引用
- 类定义
- 头文件
- 头文件保护符
- 第三章 标准库类型
- 用using声明命名空间
- string
- 读写
- size和empy
- string的操作
- 下标操作
- cctype 字符处理库
- vector集合标准库
- 初始化
- 迭代器
- bitset标准库
- 定义和初始化
- 常用操作
- 第四章 数组和指针
- 数组
- 定义和初始化
- 指针
- C风格字符串
- 动态数组
- 位操作符
- 箭头操作符
- sizeof操作符
- new 和 delete
- 动态创建对象的初始化
- 数组
- 第六章
- try和catch
- 标准异常类
- 使用预处理器进行调试
- 测试代码的处理
- 有用的常量
- assert断言
- 第七章 函数
- 函数形参实参
- 指针形参
- 引用形参
- 数组形参
- 函数声明
- 默认实参
- 局部对象
- 静态局部对象
- 内联inline函数
- 类的成员函数
- 构造函数
- 默认构造函数
- 函数指针
- 函数指针类型
- 初始化赋值和调用
- 用作形参和返回值
- 函数形参实参
- 第八章 标准IO库
- 第九章 顺序容器
- 第十章 关联容器
- 第十一章 泛型算法
- 第十二章 类
- 类定义
- 类内部的typedef
- 构造函数
- 构造函数的初始化列表
- 单形参构造函数的隐式转换
- 友元
- 类定义
- 第一章快速入门
第一章快速入门
输入和输出
操作符
<<
和>>
分别为输入操作符和输出操作符- 操作符返回的是左值,即
std::cout<<"123"<<std::endl;
等价于std::cout<<"123"; std::cout<<std::endl;
命名空间
std::
表示后面的cout
或者endl
是使用的std命名空间的定义,即标准库中的定义- 所以我们自己可以使用相同的名字,并以命名空间和标准库中的进行区分
读取未知数目的输入
while(cin>>value){...}
报错
std::cerr << "Here is an error."<< std::endl;
类的简介
头文件
- 标准库用<>,例如
#include <iostream>
,自定义类的头文件用“”,例如#include "My_class.h"
第二章变量和基本类型
wchar_t
- wchar_t是2个字节的char
宽字符/字符串
- 在字符或者字符串前面加L表示宽字符/字符串,例如
L'a'
和L"saty"
字符串连接
"Hello word"
等效"Hello "(中间可以是空格回车制表符)"world"
多行连接
- 在一行加末尾加“\”可将此行和下一行当作同一行处理
初始化
- 几种初始化的方式
#include <string>std::string titleA = "C++ Primer";//复制初始化std::string titleB("C++ Primeer");//直接初始化,推荐std::string shige9(10,'9');//string的一个特殊的初始化方法(构造函数)
- 初始化语法可以混合
#include <string>double salary = 99.99, wage(salary + 0.1);int i,j = 1,k = 2;std::string title("C++ Primer"), author = "somebody";
- 常量定义
const int a = 1;
引用
- 引用就是对象的另一个名字
int ival = 1023; int &refVal = ival;//引用必须用与该引用同类型的对象初始化 const int &r = 42;//特例是const引用,除了用对象初始化,还可以直接用右值初始化 refVal += 1;//任何对refVal的操作都会作用于ival上,即此时ival为1024
类定义
- 用 class 和 struct 关键字定义类的唯一差别在于默认访问级别:默认情况下,struct 的成员为 public,而 class 的成员为 private
- 类定义后面要加分号:
class My_class{public:...private:...};
头文件
- 对于头文件不应该含有定义这一规则,有三个例外。头文件可以定义类、值在编译时就已知道的 const 对象和 inline 函数
- 如果 const 变量不是用常量表达式初始化,那么它就不应该在头文件中定义。相反,和其他的变量一样,该 const 变量应该在一个源文件中定义并初始化。应在头文件中为它添加 extern 声明,以使其能被多个文件共享。
头文件保护符
- 会出现一个头文件被include两次,例如”A.h” #include了 “B.h”,”C.cpp”同时#include了 “A.h”和”B.h”,相当于”C.cpp” #include 了”B.h”两次
- 头文件保护符用于避免在已经见到头文件的情况下重新处理该头文件的内容(为”B.h”):
#ifndef B_H#define B_H//这里写原来的B.h的代码#endif
第三章 标准库类型
用using声明命名空间
using namespace std;
或者using std::cin; using std::string
string
读写
- cin>>string,会读取并忽略开头所有的空白字符(如空格,换行符,制表符);读取字符直至再次遇到空白字符,读取终止。
- 可以用
getline(cin, string)
读一行的字符串给string,不会带换行符
size和empy
- int string.size()
- boolean string.empty()
string的“+”操作
- 注意不能将两个字符串字面值即“”括起来的字符串常量相加,见下例:
string s1,s2 = "s2";s1 = s2 + "abc" + "def";//oks1 = "abc" + "def" + s2;//not ok
下标操作
string s1 = "big";s[2-1] = 'u';// s1变为"bug"
cctype 字符处理库
- C++中命名为< cname >的库,源自于C中的”name.h”库,不同的是< cname >头文件中定义的名字都在std命名空间,因此为了避免混淆尽量使用C++版本的< cname >库
vector集合标准库
初始化
#include <vector>using std::vector;vector<int> ivec;vector<Myclass> Myclass_vec;vector<int> vec1(vec2);//vec1为vec2的一个copyvector<int> vec3(10,-1);//vec3初始化为10个-1vector<int> vec4(10);//初始化为10个0vector<string> vec5(10);//初始化为10个空字符串(string的默认构造函数)vec5[0] = "Hello World!";//下标操作
- 常用操作
迭代器
vector<int> ivec(10);vector<int>::iterator iter = ivec.begin();//iter指向ivec[0]iter = ivec.end();//iter指向ivec[10](并不存在)*--iter = 1;//ivec[9]变为1vector<int>::const_iterator citer= ivec.begin();//const_iterator只能读不能写*citer = 1;//error
bitset标准库
定义和初始化
#include <bitset>using namespace std;bitset<16> b;//b为0x0000const int n = 32;//必须是常量值unsigned long u = 0x0001;bitset<n> b(u);//倒着存,从低阶位 100000000... 到高阶位string s = "10001100";bitset<n> b(s);//从低位到高位分别是0011000100... 也是反着存bitset<n> b(s,5,3);//从s[5]开始取3位,即00100000...bitset<n> b(s,3);//从s[3]取到最后,即001100000...
常用操作
第四章 数组和指针
数组
定义和初始化
- 常量和常量表达式:就是在编译时运行前就能确定值的表达式
const usigned buf_size = 512;char input_buffer[buf_size];//数组的维数必须用常量或常量表达式指定int ia = {0,1,2};int ib[5] = {0,1,2};//ib[3]和ib[4]会被自动置0char ca1[] = {'a','b','c'};//维数是3char ca2 = "abc";//维数是4,会自动在末尾添加'\0'char ca3[3] = "abc";//error
指针
C风格字符串
- 在使用
动态数组
int *pia = new int[10];int n = 32;int *pia2 = new int[n];//可以用任意表达式作为维数进行定义int *psa = new string[10]();//可以用默认的构造函数进行初始化int *pia3 = new int[n]();//初始化为0,只支持默认初始化,不支持初始化列表初始化delete[] pia;//释放内存空间
位操作符
箭头操作符
- “->”等效于“*”和 “.”的组合
Myclass mc = new Myclass();Myclass* mcp = &mc;mc.do_something();(*mcp).do_something();mcp->do_something();
sizeof操作符
Myclass mc,*mcp;//以下各式返回结果相同,为Myclass所占字节数sizeof(Myclass);sizeof mc;sizeof *mcp;//sizeof表达式为常量表达式,编译时即可确定值int[] *a = new int[10];sizeof(a)/sizeof(*a);//结果为10
new 和 delete
动态创建对象的初始化
int *pi = new int;//分配空间,内置类型不初始化int *pi = new int(1024);//初始化为1024int *pi = new int();//初始化为0string *ps = new string;//调用默认构造函数初始化,即初始化为空字符串string *ps = new string();//和上面等效string *ps = new string(10,'9');//初始化为10个9delete pi;//pi必须是new分配出来的pi = 0;//这样更安全
第六章
try和catch
try{ throw runtime_error("I'm an error~");} catch(runtime_error err){ cout<<err.what()<<endl;//把“I'm an error~”打印出来}int a = 0; //运行func1()后a的值为2void func1(){ try { func2(); } catch(runtime_errpr err) { a = 1;//fun2()已经把异常catch了,不会执行这行 }}void func2(){ try{ func3(); } catch(runtime_errpr err) { cout<<err.what()<<endl; } a = 2;}void func3(){ throw runtime_error("I'm an error~"); a = 3;//没有catch。不会执行这行}
标准异常类
使用预处理器进行调试
测试代码的处理
int main(){ #ifndef NDEBUG //如果NDEBUG未被定义,执行测试代码,否则跳过执行 cerr<<"starting main"<<endl; #endif}
- 可以用编译器的命令行
$CC -DNDEBUG main.c
在main.c的开头提供#define NDEBUG
预处理命令使得NDEBUG
被定义从而关闭测试代码
有用的常量
- 有四个预处理器定义的常量:
__FILE__
: 代码文件名, ex:wdebug.cc
;__LINE__
: 当前行号, ex:2017
;__TIME__
: 代码【被编译】时间, ex:19:44:40
;__DATE__
: 代码【被编译】日期, ex:Jan 12 2005
assert断言
- 使用形如
assert(isValid(param))
的方式,对assert()
括号中的表达式进行断言,如果该表达式为true则什么都不发生,如果为false且在NDEBUG
未定义的前提下,程序会终止运行并输出信息。 - 定义NDEBUG后
assert
的功能会被自动关闭
第七章 函数
函数形参实参
指针形参
void reset(int *ip){...}//可以通过用指针作形参以在函数中改变指针所指的变量的值void use_but_no_reset(const *ip){...}//可以通过将形参指定为const以保护指针指向的值不被修改
引用形参
void swap(int &v1, int &v2){...}//使用引用做形参同样可以起到改变变量值的目的且更安全自然,并且有避免复制提高效率的作用void use_but_no_reset(const int &v1){...}//不需要修改的形参尽量都用const修饰,使得调用时可传的实参范围更广(如果不用const那么就无法传一个常量进来,例如use_but_no_reset(1))void print(vector<int> v1){...}//尽量避免这么写会有复制操作,可以使用引用,或者直接传iteratorvoid print(vector<int> &v1){...}void print(vector<int>::const_iterator start, vector<int>::const_iterator end){...}
数组形参
void print(int[10] arr){...}void print(int* arr){...}//上面的两句等效,这个10没有任何卵用void print(int (&arr)[10]){...}//这样是有用的,必须传一个长度是10的数组进来
函数声明
- 函数只能定义一次,但是可以声明多次
void print(int *array, int size);
类似这样的声明,变量名array和size是可以不要的,但是可以用作辅助文档说明变量含义- 函数的声明应该放在头文件中
默认实参
- 在函数的【声明或定义中的一处】中可以提供默认实参,调用时如果给的实参数不够,则会用默认参数初始化后面的且只支持用默认实参填充末尾的形参
string screenInit(string::size_type height = 24, string::size_type width = computeSize(), char background = ' ');
局部对象
静态局部对象
size_t count_calls(){ static size_t ctr = 0;//这个变量会在第一次调用之前就初始化为0,后续的调用会一直维持原值 return ++ctr;}
内联(inline)函数
- 在函数的定义前加inline关键字,如
inline const string& shorterString(const string &s1, const string &s2){ return s1.size()<s2.size()?s1:s2; }
,其作用是避免函数调用的开销 - inline说明是一个对编译器的建议,不一定会被采用
- 适用的场景是小的,只有几行的且经常被调用的函数
- 与普通函数不同,inline函数应定义在头文件中,以使得编译器可见
类的成员函数
- 类的成员函数可以在类内定义,也可以在类外定义
- 每个成员函数都有一个隐形的形参,即调用该函数的对象
- 可以在类的声明和定义后加const,例如
double avg_price() const;
来使得该成员函数隐形持有的其调用类的指针为const,即不能修改该类的数据成员(除非是mutable的)且只能调用其const函数
构造函数
- 构造函数是public的
- 初始化列表:
class Sales_item { public: // operations on Sales_item objects double avg_price() const; bool same_isbn(const Sales_item &rhs) const { return isbn == rhs.isbn; } // default constructor needed to initialize members of built-in type Sales_item(): units_sold(0), revenue(0.0) { }//为units_sold和revenue指定初始值 // private members as before private: std::string isbn;//类类型的成员会自动用其默认构造函数初始化 unsigned units_sold; double revenue;};
默认构造函数
- 如果没有为一个类显式定义任何构造函数,编译器将自动为这个类生成默认构造函数。
- 默认构造函数会对类中的类类型成员初始化,但不会初始化内置类型成员
函数指针
函数指针类型
- 函数指针的类型由返回类型和形参决定,与函数名无关:
bool (*pf)(const string &, const string &);
初始化、赋值和调用
- 除了用作函数调用的左操作数以外,对函数名的任何使用都被解释为函数指针,可以用来初始化和赋值函数指针变量,同样可以直接使用指针进行函数调用:
typedef bool (*cmpFcn)(const string &, const string &);// compares lengths of two stringsbool lengthCompare(const string &, const string &);cmpFcn pf1 = 0; // ok: unbound pointer to functioncmpFcn pf2 = lengthCompare; // ok: pointer type matches function's typepf1 = lengthCompare; // ok: pointer type matches function's typepf1 = &lengthCompare;//与上面等效pf2 = pf1; // ok: pointer types match//以下三句等效pf1("hi","bye");(*pf)("hi","bye");lengthCompare("hi","bye");
用作形参和返回值
- 用作形参:
//下面两句等价void useBigger(const string &, const string &, bool(const string &, const string &));void useBigger(const string &, const string &, bool(*)(const string &, const string &));
- 用作返回值
int (*ff(int))(int*, int);//函数名ff,形参int,返回一个int(*)(int*,int)类型的函数指针
第八章 标准IO库
第九章 顺序容器
第十章 关联容器
第十一章 泛型算法
第十二章 类
类定义
类内部的typedef
class Screen {public:// interface member functionstypedef std::string::size_type index;private:std::string contents;index cursor;index height, width;}; //注意这里要有分号
构造函数
构造函数的初始化列表
- 初始化列表
field(0)
和构造函数内写field = 0
是不等价的,前者是初始化操作,后者是赋值操作,对于只可以初始化不可以复制的常量和引用,只可以在初始化列表中进行初始化
class ConstRef { public: ConstRef(int ii); private: int i; const int ci; int &ri;};// no explicit constructor initializer: error ri is uninitializedConstRef::ConstRef(int ii){ // assignments: i = ii; // ok ci = ii; // error: cannot assign to a const ri = i; // assigns to ri which was not bound to an object}// ok: explicitly initialize reference and const membersConstRef::ConstRef(int ii): i(ii), ci(i), ri(ii) { }
- 在初始化列表中,成员被初始化的顺序和初始化列表的写法无关,取决于定义的顺序
- 初始化式可以是任意表达式
- 初始化式可以使用类类型成员的构造函数
MyClass():youClass(va1,va2),intVar1(va1){}
- 可以使用默认实参代替两种构造函数的声明
class Sales_item {public:Sales_item(const std::string &book = ""):isbn(book), units_sold(0), revenue(0.0) { }//与下面两个声明加起来等效Sales_item():isbn(""), units_sold(0), revenue(0.0) { }Sales_item(const std::string &book):isbn(book), units_sold(0), revenue(0.0) { }};
- 一定要定义默认构造函数,不然会有很多问题
单形参构造函数的隐式转换
- 如果Class1定义了包含一个形参的构造函数,那么所有期待使用Class1类型对象的地方,都可以使用该形参的类型,编译器将用构造函数将该形参类型变量隐式转换为Class1类型对象
- 如果禁止这种隐式转换,需要在构造函数的声明前加explicit
- 通常,除非有明显的理由想要定义隐式转换,否则,单形参构造函数应该为 explicit。
友元
- 在类中一个其他的类或者其他的函数(非该类的成员函数)声明为该类的友元,可以使该类的非public成员暴露给友元
class Screen {// Window_Mgrmust be defined before class Screenfriend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index,Window_Mgr::index,Screen&);// ...rest of the Screen class};
阅读全文
0 0
- C++/C学习笔记
- 【C/C++】STL学习笔记
- C/C学习笔记/导言
- C/C学习笔记/结构
- 【c/c++】学习笔记1
- C学习笔记1
- TPC-C学习笔记
- c语言学习笔记
- C语言学习笔记
- C语言学习笔记
- 学习笔记之c
- C#-学习笔记
- Objective-C学习笔记
- C++PRIMER学习笔记
- C学习笔记
- C 学习笔记
- C/C++学习笔记
- 1.C学习笔记
- Vivado Logic Analyzer中VIO核的使用
- 【python学习笔记】12:用matplotlib绘制3D函数图像
- 高性能mysql笔记(一)并发 事务 引擎
- [PAT-乙级]1061.判断题
- 笔记本安装双系统教程
- C++学习笔记
- 莫名其妙 对话框 create 失败, 错误见图
- Mockito 测试基本用法
- 最喜欢的诗文
- 模块5
- 内部类大展身手 ———— 多个内部类以不同的方式实现同一个接口,或继承同一个类
- [PAT-乙级]1062.最简分数
- 百度2017春招<度度熊买帽子问题>Java代码
- 怎么把下划线整体下移上移,让下划线和文字距离随便调整。