身为C++的零基础初学者,短期内把《C++Primer》啃下来是一个比较笨但是有效的方法,一方面可以掌握比较规范的C++语法(避免被项目中乱七八糟的风格带跑偏),另一方面又可以全面地了解C++语法以及C++11新标准(后续要做的事情就剩下查漏补缺,不断完善自己的知识体系)。
个人感觉从零学习一门新知识比较好的方法是快速了解知识的全貌,然后构建自己的知识地图,后续不断地补充相应的细节。
由于《C++Primer》和大多数的教科书一样废话连篇,因此想要精炼一下每篇文章的内容再打印成pdf,方便温故知新。
C++支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可独立编译。
为了支持分离式编译,C++将定义和声明区分开。其中声明规定了变量的类型和名字,定义除此功能外还会申请存储空间并可能为变量赋一个初始值。如果想声明一个变量而非定义它,就使用关键字extern并且不要显式地初始化变量:
变量能且仅能被定义一次,但是可以被多次声明。
extern int i; // 声明i而非定义i extern int i = 1; // 定义i, 这样做抵消了extern的作用C++11中新增了“右值引用”,而我们这里讲的引用指的是“左值引用”。
引用必须初始化引用本身并非对象,它是一个已经存在的对象的别名因为引用本身不是对象,所以不能定义引用的引用指针只可能是以下四种情况:
指向一个对象指向紧邻对象所占空间的下一个位置空指针无效指针试图拷贝或者以其他方式访问无效指针的值都会引发错误,编译器并不会负责检查此类错误。空指针不指向任何对象,在试图使用一个指针之前最好先判断它是否为空。C++11中得到空指针最直接的方法就是字面值nullptr。
建议:初始化所有指针。访问未经初始化的指针相当于去访问一个本不存在的位置上本不存在的对象。如果指针所占空间中恰好有内容,而这些内容又被当做某个地址。我们就很难分清它是否是合法的了。因此建议初始化所有指针,并且尽量等定义了对象之后再定义指向它的指针。如果实在不清楚指针应该指向何处,就将它初始化为nullptr,这样程序就能检测并在非法引用时报错。
const对象一旦创建后其值就不能再改变,所以const对象必须初始化。
如果想在多个文件之间共享const对象,那么必须在变量的定义之前添加extern关键字。
默认状况下,const对象仅在文件内有效。const int bufSize = 512;以编译时初始化的方式定义一个const对象时,编译器将在编译过程中把用到该变量的地方都替换成对应的值。如果我们希望只在一个文件中定义const然后在其他多个文件中声明并使用它。解决的方法是对于const变量无论是声明还是定义都使用extern关键字,这样就仅需定义一次了。
// file_1.cc 定义并初始化了一个常量,该常量能被其他文件访问 extern const int bufSize = fcn(); // file_1.h 头文件 extern const int bufSize; // 与file_1.cc中定义的常量是同一个与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象。
const int c1 = 1024; const int &r1 = c1;指针本身是一个对象,它又可以指向另一个对象。因此指针本身是不是常量以及指针所指的是不是一个常量就是两个相互独立的问题。顶层const表示指针本身是一个常量,底层const表示指针所指的对象是不是一个常量。
当执行对象的拷贝操作时,拷入和拷出的对象必须具有相同的底层const资格。
常量表达式const expression是指值不会改变并且在编译过程就能得到计算结果的表达式。
C++11新标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,且必须用常量表达式初始化。
类型别名type alias是一个名字,它是某种类型的同义词。它让复杂的类型名字变得简单明了、易于理解和使用。
// 传统方法 typedef double wages; // wages是double的同义词 // 新标准 using SI = Sales_itemC++11引入了auto类型说明符,可以让编译器通过初始值来推断变量的类型。需要注意的是,编译器推断出来的auto类型有时候与初始值的类型并不完全一样,编译器会适当地改变结果类型使其更加符合初始化规则。
当引用作为初始值时,真正参与初始化的是引用对象的值 atuo一般会忽略掉顶层const,底层const会保留下来,比如当初始值是一个指向常量的指针。如果希望推断出的auto类型是一个顶层const时,需要明确指出: const int ci = i; const auto f = ci;为了确保各个文件中类的定义一致,类通常被定义在头文件中,而且类所在头文件的名字应与类的名字一样。
头文件通常包含哪些只能被定义一次的实体,如类、const和constexpr变量等 C++会使用头文件保护符来防止包含多份相同的头文件。 #ifndef SALES_DATA_H #define SALES_DATA_H #include <string> struct Sales_data { std::string bookNo; unsigned units_sold = 0; double revenue = 0.0; }; #endif C++将C语言中的头文件如name.h重命名为cname,即去掉了.h后缀同时在前面加上字母c。一般而言C++程序员应该使用cname的头文件而非name.h的形式,标准库中的名字总能在命名空间std中找到,如果使用name.h则程序员不得不时刻牢记从属于C还是C++。