内存管理+函数模板与类模板

全局变量与全局静态变量的区别:链接属性不同,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;
}
上一篇:C++收藏夹


下一篇:2021-09-26 scanf读取数目不确定的数据的方法