全局变量与全局静态变量的区别:链接属性不同,globavar在所有文件中可见,而全局静态只在该文件中可见。
malloc->operator new-> new 之间的关系
malloc new = malloc+失败抛异常;抛异常(面向对象处理错误的方式)
new = operator new +构造函数。
Date *p=operator new (sizeof(A)) 加上 new ( p )Date等价于
Date *p = new Date;
new比起malloc不一样的地方:
1.new会调用函数构造初始化。2.new失败时会抛异常。malloc失败会返回0;
delete比起free不一样的地方:
1.调用析构函数(清理资源)处理。
2.delete失败时,进程会自动终止。
operator delete 和 free没区别:因为释放空间失败都会直接终止进程。
malloc/free和new/delete的区别
1.概念性质:malloc和free是函数,new和delete是操作符
2.使用方法:malloc申请空间时要计算空间大小并传递参数,new只需在其后跟上空间的类型即可。
3.使用效果:malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常。
对于申请和释放自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数和析构函数,而new和delete会。
1.泛型模板:使用模板,编写跟类型无关的代码。
模板原理:我们自己写出一个模板,编译器通过模板产生相对的函数。
2.函数模板的实例化
函数模板的实例化分为隐式实例化和显示实例化。
隐式实例化:让编译器根据实参推演模板参数的实际类型。
例如:Add(a1,a2)
若函数模板为
Add(const T& left,const T& right)
此时若a1与a2的类型不同,则会出现编译错误。
此时处理方法有两种
1.用户自己来强制转化Add(a,(int)d)
2.使用显式实例化Add(a1,a2)
1.一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数。
2.对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数,那么将选择模板。
3.模板函数不允许自动类型转换,但是普通函数可以进行自动类型转换。
动态顺序表的实现:
#include<iostream> #include<assert.h> using namespace std; #define N 5 template<class T> class vector//动态顺序表 { public: vector(int size = 0, int capacity = 0) : _a(nullptr) , _size(0) , _capacity(0) { } void push_back(const T& date); int size() { return _size; } T& operator[](const int& i) { assert(i < _size); return _a[i]; } ~vector() { delete[] _a; _a = nullptr; _size = 0; _capacity = 0; } private: T* _a; int _size; int _capacity; }; template<class T> void vector<T>::push_back(const T& date) { if (_size == _capacity) { int newcapacity = _capacity == 0 ? 2 : _capacity * 2; T* tmp = new T[newcapacity]; if (_a) { memcpy(tmp, _a, sizeof(T)*_size); delete[]_a; } _a = tmp; _capacity = newcapacity; } _a[_size] = date; _size++; } int main() { vector<int>d_cpp_int; vector<double>d_cpp_double; d_cpp_int.push_back(1); d_cpp_int.push_back(2); d_cpp_int.push_back(3); d_cpp_double.push_back(1.1); for (int i = 0; i < d_cpp_int.size(); ++i) { //d_cpp_int.operator[](i) *=2; d_cpp_int[i] *= 2;//operator[]传返回值是为了可以修改返回对象,所以引用返回。不用引用返回的话,返回值就是一个临时空间的值(具有常性,不可改变) } for (int i = 0; i < d_cpp_int.size(); ++i) { cout << d_cpp_int[i] << " "; } cout << endl; system("pause"); return 0; }