C++自己定义并且实现一个简单的vector类模板

C++STL本身已经继承到很多模板,例如:向量模板:vector, list… 关联式容器: set, map等等。最近关于向量容器,自己动手实现了一下类似向量容器vector的一个简单实现。话不多说,直接上代码。

#ifndef _MYVECTOR_H
#define _MYVECTOR_H
#include<iostream>
#include<memory>
#include<utility>


template <typename T>
class myVector {
	typedef T            value_type;
	typedef T*           iterator;
	typedef const T*     const_iterator;
	typedef T&           reference;

	template <typename U> friend std::ostream &operator<<(std::ostream&, const myVector<U>&);
private:
	iterator    _elements;
	iterator    memory_free;
	iterator    _capacity;
	std::allocator<value_type> alloc; //myVector allocator

	std::pair<iterator, iterator> alloc_n_copy(const_iterator begin, const_iterator end)
	{
		auto new_memory = alloc.allocate(end - begin);

		return { new_memory,std::uninitialized_copy(begin,end,new_memory) };
	}
	void free(){

		for (iterator ptr = memory_free; ptr != _elements; )
			alloc.destroy(--ptr);//free dynamically allocated memory

		alloc.deallocate(_elements,memory_free-_elements);//free object allocted memeory
		_elements = memory_free = _capacity = nullptr;
	}
	void reallocator()
	{
		std::size_t newCapacity = size() ? 2 * size() : 1;

		iterator newmemory = alloc.allocate(newCapacity);

		iterator dst = newmemory;
		iterator elem = _elements;

		for (std::size_t i = 0; i != size(); ++i)
			alloc.construct(dst++, std::move(*elem++));
		free();
		_elements = newmemory;
		memory_free = dst;
		_capacity = _elements + newCapacity;

	}
	void check_n_alloc()
	{
		if (size() == capacity())
			reallocator();
	}

public:
	myVector<T>() : _elements(nullptr), memory_free(nullptr), _capacity(nullptr) {}
	myVector<T>(const std::initializer_list<value_type>& ls)
	{
		std::pair<iterator, iterator> newmemory = alloc_n_copy(ls.begin(),ls.end());
		_elements = newmemory.first;
		memory_free = newmemory.second;
		_capacity = newmemory.second;
	}
	myVector<T>(const myVector<T>& rhs)
	{
		std::pair<iterator, iterator>newmemory = alloc_n_copy(rhs.begin(), rhs.end());
		_elements = newmemory.first;
		memory_free = newmemory.second;
		_capacity = newmemory.second;
	}
	myVector<T>(myVector<T>&& rhs) : _elements(rhs._elements),
		memory_free(rhs.memory_free), _capacity(rhs._capacity)
	{
		rhs._elements = nullptr;
		rhs.memory_free = nullptr;
		rhs._capacity = nullptr;
	}
	myVector<T>& operator=(const myVector<T>&rhs)
	{
		if (*this != rhs)
		{
			std::pair<iterator, iterator>newmemory = alloc_n_copy(rhs.begin(), rhs.end());
			free();
			_elements = newmemory.first;
			memory_free = newmemory.second;
			_capacity = newmemory.second;

		}
		return *this;

	}
	reference operator[](std::size_t index) const {
		if (index > size())
			throw "out of range";
		return _elements[index];
	}

	reference operator[](std::size_t index) {
		if (index > size())
			throw "out of range";
		return _elements[index];
	}
	bool operator<(const myVector<T>& rhs)
	{
		if (this->size() < rhs.size())
			return true;
		else
			if (this->size() > rhs.size())
				return false;
		iterator rhs_element = rhs._elements;
		for (iterator ptr = _elements; ptr != memory_free;)
		{
			if (*ptr++ > *rhs_element++)
				return false;
			else
				return true;
		}
		return false;
				
	}
	bool operator==(const myVector<T>& rhs)
	{
		if (this->size() != rhs.size())
			return false;
		iterator rhs_element = rhs._elements;
		for (iterator ptr = _elements; ptr != memory_free;)
		{
			if (*ptr++ != *rhs_element++)
				return false;
		}
		return true;

	}
	bool operator!= (const myVector<T>& rhs)
	{
		return !(*this == rhs);
	}
	bool operator>(const myVector<T>& rhs)
	{
		return !(*this < rhs) && (*this != rhs);
	}

	void push_back(const T& value)
	{
		check_n_alloc();
		alloc.construct(memory_free++,value);
	}
	value_type pop_back()
	{
		
		if (_elements == memory_free)
			throw ("This is no element");
		else
		{
			value_type result=_elements[size()-1];
			alloc.destroy(--memory_free);
			return result;
		}
			
	}
	template<typename ...T>
	void emplace_back(T &&... package)
	{
		check_n_alloc();
		alloc.construct(memory_free++,std::forward<T>(package)...);
	}
	std::size_t size()const
	{
		return memory_free - _elements;
	}
	std::size_t capacity()const
	{
		return _capacity - _elements;
	}
	iterator begin()const 
	{
		return _elements;
	}
	iterator end() const
	{
		return memory_free;
	}
	void resize(const std::size_t &length)
	{
		if (length == 0)
			free();
		else
		{
			iterator newmemory = alloc.allocate(length);

			iterator dst = newmemory;
			iterator elem = _elements;

			for (std::size_t i = 0; i != size(); ++i)
				alloc.construct(dst++, std::move(*elem++));
			free();

			T value = T();
			for (std::size_t i = size(); i != length; ++i)
				alloc.construct(dst++, value);

			_elements = newmemory;
			memory_free = dst;
			_capacity = _elements + length;
		}

	}
	void reserve(const std::size_t& length)
	{
		if (length > capacity())
		{
			iterator newmemory = alloc.allocate(length);

			iterator dst = newmemory;
			iterator elem = _elements;

			for (std::size_t i = 0; i != size(); ++i)
				alloc.construct(dst++, std::move(*elem++));
			free();

			_elements = newmemory;
			memory_free = dst;
			_capacity = _elements + length;
		}
	}
};
template <typename U> 
std::ostream &operator<<(std::ostream& out, const myVector<U>& nums)
{
	for (auto iter = nums.begin(); iter != nums.end(); ++iter)
		out << *iter << " ";
	out << std::endl;
	return out;
}
#endif // !_MYVECTOR_H

对以上代码中涉及到的一些代码块进行解析

关于allocate和construct的分析

        std::size_t newCapacity = size() ? 2 * size() : 1;
        ///< allocate的作用是分配大小为“nweCapacity”的空间
        iterator newmemory = alloc.allocate(newCapacity);
  
		iterator dst = newmemory;
		iterator elem = _elements;
       ///< construct在这里的作用是通过对已分配的内存空间填充指定元素
		for (std::size_t i = 0; i != size(); ++i)
			alloc.construct(dst++, std::move(*elem++));

关于destroy和deallocate的分析

///< destroy 的作用就是将已分配的动态内存析构掉
for (iterator ptr = memory_free; ptr != _elements; )
			alloc.destroy(--ptr);//free dynamically allocated memory
///< deallocate的作用是将该对象析构掉
		alloc.deallocate(_elements,memory_free-_elements);//free object allocted memeory

destory负责调用类型的析构函数,销毁相应内存上的内容(但销毁后内存地址仍保留)
deallocate负责释放内存(此时相应内存中的值在此之前应调用destory销毁,将内存地址返回给系统,代表这部分地址使用引用-1)

本文特别重要的一个地方(emplace_back)

///<通过不断地回调该函数,将类型中的每个元素一一进行创建,切记,调用emplace_back需要给
///该类型写一个右值引用的构造函数

template<typename ...T>
	void emplace_back(T &&... package)
	{
		check_n_alloc();
		
		alloc.construct(memory_free++,std::forward<T>(package)...);
	}
///<该构造函数不可缺少
myVector<T>(myVector<T>&& rhs) : _elements(rhs._elements),
		memory_free(rhs.memory_free), _capacity(rhs._capacity)
	{
		rhs._elements = nullptr;
		rhs.memory_free = nullptr;
		rhs._capacity = nullptr;
	}

对该类模板进行功能性测试

#include<iostream>
#include<cstdlib>
#include<string>
#include<memory>
#include<vector>
#include"TestQuery.h"
#include<map>
#include"MyVector.h"
#include<algorithm>
#include<iterator>
int main(int argc,char* argv[])
{
	myVector<int> myString={0,1,1,2,3,3,4,5};
	myVector<string> myString1; 
	std::cout<<myString1.size();
	myString1.push_back("Hello");
	myString1.push_back("world");
	myString1.emplace_back("My");
	std::copy(myString1.begin(), myString1.end(), std::ostream_iterator<string>(std::cout, " "));
	myString1.resize(0);
	myString1.reserve(5);
	std::cout << myString1.size();
	std::copy(myString1.begin(),myString1.end(),std::ostream_iterator<string>(std::cout," "));
	std::cout << "Hello World!" << std::endl;
	system("pause");
}

最终的输出结果

0
My Vector Here
0
Hello World!
请按任意键继续. . .

该类模板基本上可以实现以下几个功能

push_back、pop_back、 emplace_back、 pop_back、resize(n)、以及reserve(n),还有最终的是可以和STL本身已经写好的一些算法结合起来,例如std::copy.

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值