全局变量与全局静态变量的区别:链接属性不同,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;
}