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 的区别:(参考https://blog.csdn.net/shellching/article/details/50786940)
(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 (明确的)的作用:(参考https://www.cnblogs.com/ymy124/p/3632634.html)
防止类构造函数的隐式自动转换
7. 关键字 volatile (易变的)的作用:(参考https://www.cnblogs.com/zhaoli/p/4250468.html)
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 <iostream>
#include <windows.h>
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 <<endl;
cout << ">>>>>>>>>>>>>>->->>>>"<<endl;
ts = GetTickCount();
func1(n);
te = GetTickCount();
cout << "func1: using time: "<< (te-ts)*1.0/100000 <<"\n";
cout << n <<endl;
ts = GetTickCount();
func2(n);
te = GetTickCount();
cout << "func2: using time: "<< (te-ts)*1.0/100000 <<"\n";
cout << n <<endl;
ts = GetTickCount();
func3(p);
te = GetTickCount();
cout << "func3: using time: "<< (te-ts)*1.0/100000 <<"\n";
cout << "n: " << n <<endl;
cout << "*p: " << (*p) <<endl;
p = &n;
cout << " before. p: " << p << endl;
ts = GetTickCount();
func4(p);
te = GetTickCount();
cout << " after. p: " << p << endl;
cout << "func4: using time: "<< (te-ts)*1.0/100000 <<"\n";
cout << "n: " << n <<endl;
cout << "*p: " << (*p) <<endl;
p = &n;
cout << " before. p: " << p << endl;
ts = GetTickCount();
func5(p);
te = GetTickCount();
cout << " after. p: " << p << endl;
cout << "func5: using time: "<< (te-ts)*1.0/100000 <<"\n";
cout << "n: " << n <<endl;
cout << "*p: " << (*p) <<endl;
return 0;
}
5. 基类的析构函数最好都为虚析构函数
当定义有基类指针且指向派生类的对象时,基类的析构函数若不是虚析构函数将会造成内存的泄露。
2018-09-18