当前位置 : 主页 > 编程语言 > 其它开发 >

四、模板编程——学习C++类库的编程基础

来源:互联网 收集:自由互联 发布时间:2022-05-30
一、函数模板 模板不能在一个文件中定义在一个文件中使用。 模板代码调用之前,一定要看到模板定义的地方,这样的话,目标才能够进行正常的实例化,产生能够被编译器编译的代
一、函数模板

模板不能在一个文件中定义在一个文件中使用。

模板代码调用之前,一定要看到模板定义的地方,这样的话,目标才能够进行正常的实例化,产生能够被编译器编译的代码

所以,模板代码都是放在头文件当中,然后在源文件当中直接进行#include包含

模板的非类型参数

都是常量,只能使用,不能修改

templete<typename T,int SIZE>//非类型参数
void sort(T *arr){
//排序
	for(int i=0;i<SIZE-1;i++){
		for(int j=0;i<SIZE-1-i;j++){
			if(arr[j]>arr[j+1]){
				int tmp=arr[j];
				arr[j]=arr[j+1];
				arr[j+11]=tmp;
			}
		}
	}
}

int main(){
	int arr[]={12,455,456,13,54,43};
	const int size=sizeof(arr)/sizeof(arr[0]);
	sort<int,size>(arr);//在这里使用非参数列表,后面的size是const的类型
}
二、类模板

构造和析构函数名不用加,其他出现模板的地方都加上类型参数列表

template<typename T>
class SeqStackT
{
public:

	SeqStackT(int size = 10) 
		:_top(-1),
		_size(size),
		_pstack(new T[size]) {	}

	SeqStackT(const SeqStackT& src)
		:_top(src._top),
		_size(src._top) {
		cout << this << "SeqStackT<>(const SeqStack& src)" << endl;
		_pstack = new T[src._size];
		for (int i = 0; i <= src._top; i++) {
			_pstack[i] = src._pstack[i];
		}
	}

	~SeqStackT() {
		cout << this << "~SeqStack()" << endl;
		delete[] _pstack;
		_pstack = nullptr;
	}

	SeqStackT& operator=(const SeqStackT& src) {
		cout << "operator=" << endl;
		//防止自赋值
		if (this == &src) {
			return *this;
		}
		delete[] _pstack;//需要释放掉自身占用的外部资源
		_pstack = new T[src._size];
		for (int i = 0; i <= src._top; i++) {
			_pstack[i] = src._pstack[i];
		}
		_top = src._top;
		_size = src._size;
		return *this;
	}

	void push(int val) {
		if (full()) {
			resize();
		}
		_pstack[++_top] = val;
	}

	void pop() {
		if (empty()) {
			return;
		}
		--_top;
	}

	int top() {
		return _pstack[_top];
	}

	bool empty() { return _top == -1; }
	bool full() { return _top == _size - 1; }

private:
	T* _pstack;

	int _top;

	int _size;

	void resize() {
		int* ptmp = new T[_size * 2];
		for (int i = 0; i < _size; i++) {
			ptmp[i] = _pstack[i];
		}
		delete[] _pstack;
		_pstack = ptmp;
		_size *= 2;
	}
};
三、实现vector
//
// Created by 26685 on 2022-05-15 20:33.
// Description:
//

#ifndef C___VECTORT_H
#define C___VECTORT_H

using namespace std;

template<typename T>
class VectorT {
public:
    VectorT(int size = 10) {
        _first=new T[size];
        _last=_first;
        _end=_first+size;
    }

    ~VectorT() {
        delete[] _first;
        _first = _last = _end = nullptr;
    }

    VectorT(const VectorT<T> &src) {
        int size = src._end - src._first;
        _first = new T[size];
        int len = src._last - src._first;
        for (int i = 0; i < len; i++) {
            _first[i] = src._first[i];
        }
        _last = _first + len;
        _end = _first + size;
    }

    VectorT<T> &operator=(const VectorT<T> &src) {
        if (src == *this) {
            return *this;
        }
        delete[] _first;

        int size = src._end - src._first;
        _first = new T[size];
        int len = src._last - src._first;
        for (int i = 0; i < len; i++) {
            _first[i] = src._first[i];
        }
        _last = _first + len;
        _end = _first + size;
        return *this;
    }

    void push_back(T val) {
        if (full()) {
            expend();
        }
        *_last++ = val;
    }

    void pop_back() {
        if (empty()) { return; }
        _last--;
    }

    T back() const{
        return *(_last - 1);
    }

    bool full() const{
        return _last == _end;
    }

    bool empty() const{
        return _first == _last;
    }

    int size() const{
        return _last - _first;
    }

private:
    T *_first;//表示vector起始位置

    T *_last;//表示vector定义元素的末尾

    T *_end;//表示vector的末尾

    void expend() {//size扩大两倍
        int size = _end - _first;
        T *ptmp = new T[size * 2];
        for (int i = 0; i < size; i++) {
            ptmp[i] = _first[i];
        }
        delete[] _first;
        _first = ptmp;
        _last = _first + size;
        _end = _first + (2 * size);
    }
};


#endif //C___VECTORT_H
//实现
int main() {
   
    VectorT<int> vec;
    for(int i=0;i<15;i++){
        vec.push_back(rand()%100);
    }
    while (!vec.empty()){
        cout<<vec.back()<<" ";
        vec.pop_back();
    }
    cout<<endl;
    return 0;
}

空间配置器Allocator

使用空间配置器实现vector容器:

//
// Created by 26685 on 2022-05-15 21:29.
// Description: AllocatorT.h
//
#include <cstdlib>
/**
 * 定义容器的空间配置器,和C++标准库的allocator的实现一致
 * @tparam T
 */
template<typename T>
struct AllocatorT {
    T *allocate(size_t size) {//负责内存开辟
        return (T *) malloc(sizeof(T) * size);
    }

    void deallocate(void *p) {//负责内存释放
        free(p);
    }

    void construct(T *p, const T &val) {//负责对象构造
        new(p) T(val);//定位new
    }

    void destory(T *p) {//负责对象析构
        p->~T();//析构函数
    }

};

vector类:

//
// Created by 26685 on 2022-05-15 21:29.
// Description: VectorT.h
//

#include "AllocatorT.h"

using namespace std;

/**
 * 容器底层内存开辟,内存释放,对象构造和析构都通过allocator实现
 * @tparam T
 * @tparam Alloc
 */
template<typename T, typename Alloc=AllocatorT<T> >
class VectorT {
public:
    VectorT(int size = 10) {
//        _first=new T[size];
        _first = _alloctor.allocate(size);
        _last = _first;
        _end = _first + size;
    }

    ~VectorT() {
//        delete[] _first;
        //使用allocator对vector逐个删除
        for (T *p = _first; p != _last; p++) {
            _alloctor.destory(p);
        }
        _alloctor.deallocate(_first);
        _first = _last = _end = nullptr;
    }

    VectorT(const VectorT<T> &src) {
        int size = src._end - src._first;
//        _first = new T[size];
        _first = _alloctor.allocate(size);
        int len = src._last - src._first;
        for (int i = 0; i < len; i++) {
//            _first[i] = src._first[i];
            _alloctor.contruct(_first + 1, src._first[i]);
        }
        _last = _first + len;
        _end = _first + size;
    }

    VectorT<T> &operator=(const VectorT<T> &src) {
        if (src == *this) {
            return *this;
        }
        //delete[] _first;
        for (T *p = _first; p != _last; p++) {
            _alloctor.destory(p);
        }
        _alloctor.deallocate(_first);

        int size = src._end - src._first;
        _first = new T[size];
        int len = src._last - src._first;
        for (int i = 0; i < len; i++) {
//            _first[i] = src._first[i];
            _alloctor.contruct(_first + 1, src._first[i]);
        }
        _last = _first + len;
        _end = _first + size;
        return *this;
    }

    void push_back(T val) {
        if (full()) {
            expend();
        }
        //*_last++ = val;
        _alloctor.construct(_last, val);
        _last++;
    }

    void pop_back() {
        if (empty()) { return; }
        --_last;
        _alloctor.destory(_last);
    }

    T back() const {
        return *(_last - 1);
    }

    bool full() const {
        return _last == _end;
    }

    bool empty() const {
        return _first == _last;
    }

    int size() const {
        return _last - _first;
    }

private:
    T *_first;//表示vector起始位置

    T *_last;//表示vector定义元素的末尾

    T *_end;//表示vector的末尾

    Alloc _alloctor;//负责内存管理

    void expend() {//size扩大两倍
        int size = _end - _first;
//        T *ptmp = new T[size * 2];
        T *ptmp = _alloctor.allocate(2 * size);
        for (int i = 0; i < size; i++) {
            //ptmp[i] = _first[i];
            _alloctor.construct(ptmp + i, _first[i]);
        }
        //delete[] _first;
        for (T *p = _first; p != _last; p++) {
            _alloctor.destory(p);
        }
        _alloctor.deallocate(_first);

        _first = ptmp;
        _last = _first + size;
        _end = _first + (2 * size);
    }
};

main函数实现:

#include <iostream>
#include "header/vectorT.h"

using namespace std;

struct Test {//测试类,只测试三种函数

    Test() {
        cout << "Test()" << endl;
    }

    Test(const Test& src){
        cout<<"Test(const Test& src)"<<endl;
    }

    ~Test() {
        cout << "~Test()" << endl;
    }
};

int main(){

    Test t1,t2,t3;

    cout<<"______________________"<<endl;

    VectorT<Test> vec;
    vec.push_back(t1);
    vec.push_back(t2);
    vec.push_back(t3);

    cout<<"______________________"<<endl;
    vec.pop_back();
    cout<<"______________________"<<endl;

    return 0;
}
上一篇:如何使用css绘制三角形
下一篇:没有了
网友评论