1. 双精度变量与0的比较:
const double eps = 0.000000001; double a = 0.00000000001; double b = 0.000000002; if (a >= -eps && a <= eps) // if(a <= -eps || a >= eps) cout << "a == 0" << endl; else cout << "a != 0" << endl; if (b >= -eps && b <= eps) cout << "b == 0" << endl; else cout << "b != 0" << endl;
2. 参数列表、初始化列表:
.h:class Complex {public: //外部接口 Complex(double real=0.0, double imag=0.0); //另外,带有默认值参数应放在列表的最右端 //Complex(double real, double imag=0.0)private: //私有数据成员 double real; //实部 double imag; //虚部}.cpp: //带有默认值参数的函数,在实现的时候,参数上是不能有值的 error: Complex::Complex(double real=0.0, double imag=0.0){...} //另外,只有构造函数能使用初始化列表,其在构造函数执行前执行 Complex::Complex(double real, double imag) :real(real), imag(imag){}
3. 重载单目运算符(一元运算符)++ 、--:
前置与后置的区分:(1)后置带有整型形参;
(2)前置返回计算后的值,后置返回计算前的值。
4. 重载赋值运算符‘=’:
(1)首先,需要进行是否是自我赋值操作的验证;
(2)其次,要释放左操作数的资源:
方法1 先保存原来的资源,等重新分配资源完成以后再释放以前的资源),
方法2 采用copy and swap技术;
(3)返回类型,为了具有连续赋值的效果,一般都返回引用类型。
5. new / delete 和 malloc / free 的区别:(参考)
(1)new / delete是运算符,malloc / free是函数;
(2)无法new一个抽象类,但是可以malloc出一块抽象类的空间;
(3)new/delete会调用构造/析构函数,malloc / free只分配/释放空间;
(4)new内存分配失败时,会抛出bac_alloc异常,malloc分配内存失败时返回NULL;
(5)C++允许重载new / delete操作符,而不允许重载malloc / free。
6. 关键字 explicit (明确的)的作用:(参考)
防止类构造函数的隐式自动转换
7. 关键字 volatile (易变的)的作用:(参考)
volatile的意思是让编译器每次操作该变量时一定要从内存中真正取出,而不是使用已经存在寄存器中的值;
防止编译器对变量进行优化。
2018-09-15
1.尽量用const、enum、inline替换 #define (宁可 以编译器替换预处理器)
#define 只是做替换操作,不会进行类型检测等。
- 对于单纯变量,最好用const、enum代替#define
- 对于形似函数的宏,最好用inline函数代替#define
2.
.h:class Student{private: static int num_1; const int num_2; static const int num_3 = 3; enum{num_4=4}; int arr[num_?]; // 3、4 };.cpp int Student::num_1 = 1;const int Student::num_2 = 2;const int Student::num_3; //有些编译器坚持要看到定义式,在声明时已赋值,这里不能再设值
3. const 声明的变量
int a = 1;const int* p = &a; // (*p)++ 不可用 p++可用//(不能通过指针改变变量a的值,指针指向的地址可变)int const* p = &a ; //同上int* const p = &a ; //(*p)++ 可用 p++不可用const int* const p = &a ;//(*p)++ 可用 p++可用
4. 函数形参中的值传递和引用传递
#include#include using namespace std;void ssss(){ const int s = (unsigned int)(-1) >> 5; int i = s; while(i)i--;}int func1(int a) // not change n{ //ssss(); a = 1;}int func2(int &a) // changed n{ //ssss(); a = 2;}void func3(int* p) // changed n{ //ssss(); int a = 3; *p = a;}void func4(int* p) // not change n and not change p{ //ssss(); int a = 4; p = &a;}void func5(int* &p) // not change n but it will change p{ //ssss(); int a = 5; p = &a; //the p point to a temporary variable(临时变量), //when this func over,the temporary variable will be released, //so the (*p) maybe not is a's value}int main(void){ DWORD ts,te; ts = GetTickCount(); int n = 0; int *p = &n; cout << n < >>>>>>>>>>>>>->->>>>"<
5. 基类的析构函数最好都为虚析构函数
当定义有基类指针且指向派生类的对象时,基类的析构函数若不是虚析构函数将会造成内存的泄露。
2018-09-18