关于c++:读完某C神作我只记住了100句话

7次阅读

共计 8124 个字符,预计需要花费 21 分钟才能阅读完成。

  • 假如 p 是指针,当 delete p; 时,前面肯定要 p =NULL 将 p 指向空
  • cin cout cerr 都是 iostream 类型的对象。cout\<\<“hello world”\<\<endl; 其中 cout 是左操作数对象,\<\< 是操作符,作用是将右操作数写到左操作数对象,”hello world” 是右操作数,后面半句话的意思是将 hello world 写入 cout 对象。同理,\<\<endl 是将 endl 写入 cout,endl 示意刷新缓冲区并换行。
  • std::cout :: 是作用域操作符,示意 std 名空间下的 cout,用来区别其它名空间同名变量。
  • 正文不能嵌套:/\ /\…\/ \/ 是谬误的
  • 示意整数、字符和布尔值的算术类型合称为整形。辨别类型是因为只有晓得某地址值的类型,能力晓得须要多少位示意这个变量和如何解释这些位。
  • 整形赋值超出取值范畴,会被赋值数对该类型数值数目取模后的值。
  • long 类型运行时代价远高于 int 类型。以 0 结尾的字面值常量示意八进制、以 0x 结尾的示意十六进制。任何字符能够示意为 \ooo【ooo 示意一个八进制数】
  • 对象是内存中具备类型的区域。初始化不是赋值,初始化是创立并赋值。定义在函数体外的内置变量主动初始化成 0,定义在函数体内的内置变量不进行主动初始化,类类型 \(string\)调用默认构造函数初始化。
  • const 把一个对象转换成一个常量【const int bufSize = 512】。全局变量加 const 作用域只在本文件。再加 extern 可在整个程序拜访。非 const 变量默认为 extern。
  • 援用初始化后始终绑定到初始化的对象,不能扭转【援用自身不占存储单元】。const 对象必须由 const 援用指向【防止一个能批改,一个不能批改,既对象自身和代表其的援用必须同时为 const】。一般援用不能初始化为常量,const 援用能够。
  • typedef 用来定义类型的同义词。
  • 头文件用于申明,不是定义,因此能够呈现屡次。定义的语句不应该放在头文件里,呈现两次会导致多重定义链接谬误。例外是头文件能够定义类,还有值在编译时就曾经晓得的 const 对象,还有 inline 函数。变量是申明还是定义看是否有 extern,但不是相对的,函数就看有无大括号 \{\}
  • 两个迭代器指向同一个元素就相等【==】,否则不等。任何扭转 vector 长度的操作都会使已存在的迭代器生效。difference\_type 存储迭代器间间隔。
  • 设计良好的程序只有在强调速度时才在类实现的外部应用数组和指针。数组下标的正确类型是 size\_t。
  • 预处理器变量 NULL 在编译时会被数值 0 替换。指针做减法操作失去的是 ptrdiff\_t 类型。指针 p – 2 等效 p\[-2\]。
  • 定义的多个变量具备雷同的类型,就能够在 for 循环的初始化语句中同时定义他们。for\(int a, b, c …\)
  • C++ 强制要求指向 const 对象的指针也必须具备 const 个性,能够把非 const 对象地址赋给 const 指针。
  • const 指针:int \*const cur = \&cuss; 指向 int 型变量的指针,并且自身不能批改。
  • C 格调字符串:const char \*cp = “some value”; strlen\(用于计算 c 格调字符串字符个数,不包含串最初的 ’\0’\)
  • 动静数组:int \*p = new int\[任意表达式,变量等 \] delete \[\] p;
  • new/delete 是操作符,岂但管制内存而且执行构造函数和析构函数,malloc/free 是规范库函数,不在编译器管制权限内,不能执行结构和析构。
  • 应用数组初始化 vector:int int_arr[arr_size] = {0,1,2,3}; vector<int> ivec(int_arr, int_arr+arr_size);
  • int ival; int \*pval; ival = pval = 0; 谬误,pval = 0 返回的是指针,无奈赋值给 int。
  • ++i i++ 前置时返回自增后的值,后置时返回值后自增。前置性能好于后置。
  • 逗号表达式的后果是其最左边表达式的值。
  • if\(ia\[index++\]\<ia\[index\]\)这个表达式没有明确的计算程序。除了 \&\& || \?:: 外其余操作数没有规定计算程序。不应该应用这种表达式,后果无奈确定。
  • int val = 3.24+3; 表达式先转换为高精度,再转换为左值类型。int \*ip; ip=0; 隐式转换 0 为空指针。
  • 蕴含 signed 和 unsigned int 的表达式会被转换成 unsigned,如果为正数会有问题。
  • 数组名用做 sizeof 或取地址 \& 的操作数时不被当做指针。sizeof 计算栈中调配大小,动态变量在全局数据区不计算在内。
  • const\_cast 增加或删除 const 个性。
  • 空语句:;
  • switch case break 的判断表达式必须为整数值。case 从匹配的开始执行直到完结,而不是只执行匹配的。
  • do\{此处定义的变量循环条件中不可见 \}while\(…\)
  • throw 类型 每一个规范库异样类都有 what\(\)函数返回 C 格调用户输出的字符串。如果不存在 catch 语句,程序默认执行 terminate 的规范库函数。
  • 预处理器定义的调试用的常量:\\_FILE\\ \\LINE\\ \\TIME\\ \\DATE\\_【打印工夫和日期很罕用】
  • assert 宏用来查看不可能产生的条件。
  • 函数实参如果和定义类型不统一,但可被转换成定义类型,那么也能够应用。
  • 如果须要爱护指针指向的值,形参须要定义为指向 const 的指针。应将不批改实参的形参定义为 const 援用,益处是能够传递字符串字面值(和产生右值的表达式),非 const 援用反而不灵便。
  • 如果形参是援用,那么他只是实参的别名。int \*\&v v 是援用,是某个指向 int 的指针的别名。
  • fun\(int\*\) fun\(int\[\]\) fun\(int\[10\]\)等价,但 10 其实没有任何用途。如果定义为 fun\(int \(\&arr\)\[10\]\),此时会查看参数是否有 10 个。
  • C 格调字符串以 NULL 结尾是为了标识完结避免越界

含有可变形参的函数:fun(parm_list, …)与省略符对应的实参暂停类型查看。

  • 返回值为 viod 的函数只能应用 return; 不能 return expression。return; 也只能用于返回值为 void 的函数。
  • 动态变量只在首次调用时初始化,static size_t ctr= 0 只执行一次。
  • 内联函数防止函数调用的开销:编译时开展为函数体中的表达式,免去函数调用的寄存器保留复原、复制实参跳转等。
  • 内联函数定义在头文件。编译器将类内定义的成员函数当做内联函数。
  • 每个成员函数都有一个隐含的 this 指针。假如有成员函数 bool same_isbn(..) const 最初的 const 扭转了隐含的 this 形参的类型,这种成员函数叫常量成员函数,无奈批改对象自身。const 的对象,指针援用只能调用常量成员函数。
  • 没有前缀的成员都被假设为 this 在调用。
  • 默认构造函数按变量初始化规定初始化类中所有成员【内置类型作为局部变量时不初始化】。
  • 指向函数的指针:函数类型由返回值和形参决定,与函数名无关。函数名自身就是指针。fun==&fun Fcn pf=add pf(1,2)==(*pf)(1,2)
  • 函数的形参能够是指向函数的指针:FUN(bool(string&, string&) ) 或 FUN(bool (*)(string&, string&) )。FUN 是函数名,FUN(这里都是形参)
  • iostream 定义读写管制窗口的类;fstream 定义读写已命名文件的类;sstream 定义的类型用于读写内存中的 string 对象。后面加上 w 反对 wchar_t 类型。
  • 流的状态能够由 bad,fail,eof,good 函数取得,cin.fail()。
  • 每一个流都关联一个缓冲区,解体的程序不会主动刷新缓冲区,如果用输入调试程序,确保每次输入都 flush 或 endl。tie 函数可将 istream 和 ostream 绑一起,输出前首先会刷新输入。
  • fstream 既要定义对象又要捆绑文件【open 或初始化时】。如果想用一个文件流对象读取多个文件,必须 close()并 clear()。所有流都能够用 << 操作符。
  • 设置或革除多个二进制位状态:能够屡次调用 setstate,clear;能够用位或操作符在一次调用中传递多个状态的值。A| B 生成了一个值,其对应于 A 和 B 的位都关上了,设置为 1,其余都是 0.
  • 援用不反对个别意义的赋值运算,没有容器的元素是援用。容器的容器 < < 之间必须有空格否则会被认为是 << 移位操作符。
  • vector deque 反对通过元素的地位实现随机拜访,所以迭代器能够实现算术和关系运算。list 容器的迭代器不反对算术运算(加减法 iter+n,iter1+iter2),也不反对关系运算(<= < >= >【是元素的比拟,相似于 string】),只反对 ++ — == !=。
  • 由容器定义的类型:size_type iterator value_type reference…
  • list deque 提供了 push_front()。容器元素都是正本。insert push 可能导致迭代器生效,当编写循环将元素插入到 vector deque 时,必须更新迭代器。size()返回个数,empty()返回布尔值。
  • 如果容器 c 为空,c.front() c.back()操作未定义!c[n]和 c.at(n)只实用于 vector deque,n<0 或 n >=c.size()操作未定义【c.at(n)会抛 out_of_range】。
  • 容器操作函数 find(begin, end, val) 返回值是迭代器,没找到返回 end。
  • 容器类型和元素类型都雷同,能够用赋值 vec1=vec2。容器类型不同或元素类型不同,然而兼容能够用 assign 函数来赋值。
  • vector 容器中的元素以间断的形式寄存【动静数组】。有事后调配策略,须要重新分配时加倍以后容量。capacity 函数获取目前可能存储的元素总数,reserve 函数设置 capacity。
  • string 中的字符也是间断存储的,也有迭代器 string::iterator。string 类将 string::npos 定义为保障大于任何无效下标的值。
  • 实质上,适配器是使一事物的行为相似于另一事物的行为的一种机制。stack queue priority_queue
  • pair 类型:pair<T1, T2> p1;p1.first p1.second。makepair 函数能够创立 pair 对象。vector<pair<int, int> > 如果须要多个 pair 能够放在一个 vector 中。
  • set 中元素不反复,相当于只有键没有值。map 的函数大部分都有对应的。
  • 关联容器:容器元素依据键的秩序排列。
  • map 能够了解为关联数组,键就是下标。
  • map 能够用迭代器遍历,按键排序。应用 map 的 insert 函数能够防止应用下标操作的副作用:不必要的初始化【如果 key 曾经在 map 中则 map 放弃不变,防止了初始化】
  • 带有 pair 形参的 insert 版本返回一个迭代器和一个 bool 值的 pair 对象。map.count(k)返回 k 呈现的次数。map.find(k)若 k 存在返回迭代器。map 的 erase 返回 void。
  • multimap 雷同键对应的元素必然相邻寄存。multimap.lower_bound(k)指向键不小于 k 的第一个元素,upper_bound(k)。equal_range(k)返回 pair 代表上上限。
  • 泛型算法:find 函数基于迭代器,不同容器可应用雷同 find。算法从不增加和删除容器元素。it=find_first_of(it,…)可用于多种容器。
  • accumulate(..)累加 fill 写入元素 back_insert 插入迭代器能达到 push_back 的成果 copy replace_copy sort unique count_if 谓词是检测函数。
  • 流迭代器:拜访特定类型的输出 istream_iterator<int> cin_it(cin) 反向迭代器:reverse_iterator
  • const_iterator 用于指定范畴的迭代器必要类型统一。容器返回的迭代器是否 const 取决于容器元素是否 const。
  • map set list 提供的是双向迭代器。string vector deque 提供的是随机拜访迭代器【sort 函数须要随机迭代器】。istream_iterator 是输出迭代器,ostream_iterator 是输入迭代器。
  • 对于 list 对象应该优先应用 list 容器特有的成员版本【能增加删除元素】,而不是泛型算法。
  • 简略说,类就是定义了一个新的类型和一个新的作用域。成员拜访级别默认公有。在申明和定义处指定 inline 都是非法的。类的前向申明个别用来编写相互依赖的类。类定义以分号完结,之后能够跟对象列表。
  • mytye.func1().func2()想要这种模式,就必须返回 *this 的援用能力调用 func2。成员函数是否为 const 等同于形参 this 是否 const,所以能够重载。mutable 用来申明数据成员能够批改【冲破各种 const 的限度】。
  • 应用类外全局作用域的变量能够::var 来取得。
  • 类中的 const 成员必须在初始化列表中初始化,无奈再构造函数体内赋值。初始化 const 或援用类型或没有默认构造函数的类类型数据成员的惟一机会是构造函数的初始化列表【冒号开始,逗号分隔】。初始化程序由定义程序决定,而不是初始化列表程序。
  • 友元:将非公有成员的拜访权授予指定的类或函数。friend 在类定义外部。友元引入的类名和函数(定义或申明)能够像事后申明的一样应用。
  • static 成员函数没有 this 形参,可间接拜访类的 static 成员,不能应用非 static 成员。
  • 静态数据成员属于一个类,而不属于类的各个对象。动态成员函数在所有对象建设之前或删除之后依然应用。
  • 初始化时是否调用复制构造函数取决于是否有 =【拷贝构造函数,复制也叫拷贝构造函数是用同一个类的一个对象初始化另一个对象,一般构造函数是用各种参数初始化一个类的对象】。构造函数如果是 explicit 必须严格依照定义应用构造函数,否则能够存在隐式转换。
  • 非援用形参将复制实参值,非援用 return 将复制 return 的货色。即便定义了其余构造函数,也会合成复制构造函数【可能复制类中的数组】。类成员有指针个别须要显示定义复制构造函数。
  • 申明而不定义成员函数是非法的,然而应用将导致链接失败。将复制构造函数申明为 private 可避免复制。定义了复制构造函数,也必须定义默认构造函数。
  • 重载赋值操作符 =,隐含的第一个参数 this。复制构造函数、赋值操作符、显示析构函数【虚空不算】个别同时呈现。合成析构函数并不删除指针成员指向的对象。即便编写了本人的析构函数,合成析构函数依然运行。
  • 默认构造函数不全,会调成员的默认构造函数,复制构造函数不全就不行了。
  • 应用计数是治理智能指针类的通用技术。
  • 重载操作符:保留字 operator 前面接须要定义的操作符符号,返回类型和参数表和其它函数一样。只能重载已有的操作符,只针对类类型,最好重载本来对类类型无意义的操作符。
  • 应用算法 sort 等时会假设一些操作符 (<) 存在,此时要为类型定义重载操作符。重载操作符如果是成员函数,左操作数必须是该类的对象【肯定是 this】。
  • 用函数或类操作某个类的数据可设置其为友元。== < 的逻辑定义如果不统一,不定义 < 比拟好。()是调用操作符,有这个的类称为函数对象,行为相似函数。函数对象作为算法实参,比函数更灵便。规范库中有几个函数对象。
  • 函数对象的函数适配器:绑定器 bind1st 将给定值绑定到二元对象函数第一个实参 bind2nd 第二个实参。求反器 not1 not2 count_if find_if
  • 转换操作符:operator type() type 示意内置类型名,类类型名或别名。【operator int(); // 重载类型转换操作符,能够做到 int i; Integer it; i = it; //it 间接转为 int 类型,而后赋值给 i 例如:Integer::operator int() {return data;data 是 Integer 的公有成员}】
  • virtual 函数是基类心愿派生类从新定义的函数,心愿派生类继承的函数不能为虚函数。根类个别要定义虚析构函数。
  • 派生类只能通过派生类对象拜访 protected 成员,不能用基类对象拜访。基类定义为 virtual 就始终为虚函数,派生类写不写 virtual 都是虚函数。用做基类的类必须是已定义的。
  • 存在虚函数 + 指针或援用 == 产生多态。非虚函数编译时就按指针或援用或对象类型确定。能够应用域操作符强制调用基类虚函数【虚中调虚】。基类虚函数和派生类的默认实参要统一。
  • 派生类继承基类的访问控制标号【何种形式继承】无论是什么,不影响派生类应用基类成员,但影响应用派生类的用户拜访基类成员。类应用接口继承还是实现继承对派生类用户具备重要含意。
  • 友元关系不继承。
  • 派生类指针可主动转换到基类指针,反之不行。如果晓得基类到派生类的转换【这种转换是基类地址赋给派生类指针】是平安的【就是说心里分明基类指针指向的的确是派生类】,能够应用 static\_cast 强制编译器进行转换。dynamic\_cast 是在运行时进行查看。
  • 构造函数无奈继承,派生类结构数还要初始化基类【否则只能用合成构造函数初始化】。初始化列表和初始化的程序无关。只能初始化间接基类。
  • 赋值操作符必须避免本身复制【赋值之前会先开释本身的内容,万一是本人,那不就失落了】。派生类析构函数不负责革除基类成员,每个析构函数只负责革除本人成员。派生类指针的动态类型和动静类型不统一时【基类指针指向派生类是时】,为保障删除指针调用适合的析构函数【多态】,基类析构必须为 virtual。
  • 构造函数是对象动静类型确定之前运行的,不须要定义为 virtual。
  • 援用、对象、指针的动态类型决定了可能实现的行为,动静类型有多的性能也无奈应用。派生类应防止与基类成员名字抵触。部分作用域中申明的函数不会重载全局域的函数。派生类定义的函数也不重载基类函数【想重载要么不定义,要么全定义】。using 作用域。
  • 纯虚函数 == 抽象类 == 无奈创建对象 派生类对象复制到基类时派生类对象将被切掉【而指针和援用不会】。
  • 对象不反对动静绑定,指针和援用反对但应用起来麻烦,解决办法是定义包装类或句柄类【提供到其它类接口的类】。像应用指针一样应用句柄而不必治理它指向的对象。相似智能指针的办法建设指针句柄。
  • 关联容器的构造函数是咱们可能提供比拟函数的名字:std::multiset\<Sales\_item, Comp【比拟器】> items\(compare【比拟函数】\);
  • template \<typename T> 模板定义以关键字 template 开始【旧程序中可能用 class】,后接模板形参表,模板形参表是由尖括号扩住的一个或多个模板形参的列表,以逗号分隔。表中能够有非类型形参,实例化时绑定值。
  • 通过在成员后面加上 typename 通知编译器将成员当做类型。泛型代码两个准则:1. 模板形参是 const 援用 2. 函数体中只用 \< 比拟
  • 模板形参数量自在,能够设定返回值为一个形参。显示提供实参:long a=sun\<long>\(i, lng\)
  • export 关键字可能指明给定的定义可能会须要在其余文件中产生实例化。非类型形参的模板实参:template\<int hi, int wid> 实例化时必须是常量表达式 Screen\<24,80>
  • 模板中的友元示意任何实例能够拜访任何实例。模板类中能够有模板类成员。
  • 模板类中的 static 成员由同一实例化的对象共享,但不同模板形参的实例化对象间不共享。
  • 模板特化:template\<> 模板名 \< 模板形参 > 函数形参表 函数体 特化类 也能够只特化类中某个成员 局部特化:多个模板形参,特化某个形参【编译器会优先选择特化的】。匹配同样好时,非模板版本优先。
正文完
 0