1、 循环遍历标准库元素时,最好使用 != 进行操作,而非 < 判断。获取大小的size()函数可以放在循环语句中写,一般size()函数都被设置为内联函数,性能影响很小。
2、 标准库size()函数返回元素个数,应该使用size_type子类型接收,而非使用int型变量。索引也应该使用size_type类型。
3、 Vector<>::iterator 支持减法操作,itr1 – itr2 结果值为difference_type类型。该类型与size_type类型都由vector定义。其他标准库容器不支持该操作。Deque也支持该操作。
4、 内置数组,元素个数和索引的正确类型为size_t,定义为无符号整型。
5、 两个指针支持减法操作,ptr1 – ptr2 结果值为 ptrdiff_t 类型,在标准库中定义。是一个signed类型。
6、 指针是内置数组的迭代器。内置数组超出末端的指针与通过容器的end()函数返回iterator类似。如下代码正确:
const size_t arr_sz = 5;
int int_arr[arr_sz] = {0,1,2,3,4};
for(int *pBegin = int_arr,*pEnd = int_arr + arr_sz; pBegin != pEnd; ++pBegin)
cout << *pBegin << ‘ ‘;
7、 指针和typedef放一起使用往往会带来意外的结果。
String s;
Typedef string *pString;
Const pstring cstr1 = &s;
Pstring const cstr2 = &s;
String* const cstr3 = &s;
都表示为const指针,指针本身值不能改变。
8、 利用标准库函数处理C风格字符串时,必须记住C风格字符串必须以NULL字符结束。
Cont char* str1 = “Les’t go to Have Supper”;
Const char* str2 = new char[strlen(str1) + 1]; // 分配空间必须多分配一个,存储NULL
Strcpy(str2,str1);
Delete str2 [];
9、 自增操作 i++与++i,++i的性能更高,应该尽量使用++i,而非i++,++i直接将i的值加1并返回,而i++,需要先将i的值保存,然后使i值加1并返回保存的未增加的i值。对于整数类型,编译器可以优化掉该步骤,但对于迭代器类型,后置操作符可能需要额外的代价。
10、 自增操作运算
j = i++;
此时j的值与i相等,i的值加了1。
J = ++i
此时j的值为i+1,i的值为i+1。
若itr为一个迭代器,指向容器第一个元素
Cout << *itr++ << endl;
先使itr自增,然后itr ++ 的返回值为itr未修改前的结果,输出的是第一个元素的值,而非第二个元素。
11、 对于内置数据类型,动态创建对象
int* pi1= new int;
int* pi2= new int();
第一句话pi1中的值是未初始化的,第二句话中的值被初始化为0。
对于类类型以上两中初始化方法一致,都调用类的默认构造函数进行初始化。
12、 现代C++程序应该尽量使用标准库string类型和vector类型。而不是使用C风格字符串(char*、const char*),内置数组(动态数组)。String和vector能写出可读性更强,出错几率更小的程序。
13、 程序中尽量少使用强制类型转换,若要使用,应该尽量使用C++的强制类型转换,而非从C语言继承而来的两种风格。使用const_cast一般意味着设计存在缺陷。使用reinterpret_cast本质上依赖于机器,非常危险,尽量避免使用。Static_Cast和dynamic_Cast各有各的用处,但都不应该频繁使用。
14、 空语句并不总是无害的。
Int I = a + b;; // 多一个空语句,没关系
While(itre != svec.end()) ; // 空语句、导致无限次循环
++itre;
15、 Switch语句的case块中,只有在最后一个case标号或default标号后定义变量,其他的case标号要定义变量,可以使用语句块。
switch(i)
{
case 1:
case 2:
string str = "HI,Angle!";
default:
cout << str << endl; // 若不为2、则str未定义
break;
}
16、 传递字符串等类类型参数时,若不改变实参值,建议使用const引用类型,可以防止类的拷贝,提高效率。(转换为LPCTSTR更影响效率)。
17、 预处理命令定义了其余四种再调试时非常有用的常量:
_ _ FIEL _ _ 文件名
_ _ LINE_ _ 当前行号
_ _TIME _ _ 文件被编译的时间
_ _DATE _ _ 文件被编译的日期
18、 内联函数对编译器而已只是一个建议,是否真正内联取决于编译器。可能发生在代码编写期,编译期,链接期,甚至在程序安装期和运行期。
19、 构造函数初始化列表中必须对在类内部定义的const或引用类型成员以及没有默认构造函数的类类型的任何成员使用初始化式。
20、 构造函数初始化列表中成员定义的顺序和成员的初始化顺序无关。成员变量初始化的顺序与其声明的顺序相同。
21、 虚函数与默认实参:默认实参的确定是在编译时确定的。如果一个调用省略了具有默认值的实参,则所用的值由调用该函数的类型定义。通过基类的引用或指针调用虚函数时,默认实参为在基类虚函数声明中指定的值。如果通过派生类的指针或引用调用虚函数,则默认实参是在派生类的版本中声明的值。(在同一个虚函数的基类版本和派生类版本中使用不同的默认实参几乎一定会引起麻烦)
22、 C++中通过class关键字与struct关键字定义类的区别有:
1) 默认成员保护级别:class 中为private,struct 中为public。
2) 默认派生保护级别:class 中为private,struct 中为public。
23、 友元关系不能继承。一个类是基类的友元,通过派生类对象不能访问任何private成员。