初夏小談:vectorのシミュレーション実装(二)浅いコピー問題の解決

8795 ワード

前回実装されたvectorでは、拡張でmemcpyを使用して要素のコピーを行いますが、データの位置を別の空間にコピーします.これにより、後続の元の空間が解放されると、このリソースが解放され、この新しい空間が指すリソースが失効します.プログラムがクラッシュします.だから深いコピーを行います.
コードは次のとおりです.
#include
#include
using namespace std;

namespace FirstVector
{
	template
	class vector
	{
	public:
		typedef T* iterator;
		typedef T* reverse_iterator;
	public:
		//******************************************************************************
		//       
		//1.  
		vector()
			: _start(nullptr)
			, _finish(nullptr)
			, _endOfStorage(nullptr)
		{}
		//1.2
		vector(size_t n, const T& data = T())
		{
			_start = new T[n];
			for (size_t i = 0; i < n; i++)
			{
				_start[i] = data;
			}
			_finish = _start + n;
			_endOfStorage = _finish;
		}
		//1.3
		vector(T*first, T*last)
		{
			size_t size = last - first;
			_start = new T[size];
			_finish = _start;
			T* First = first;
			while (First != last)
			{
				*_finish = *First;
				First++;
				_finish++;
			}
			_endOfStorage = _finish;
		}
		//      
		//        
		vector(vector& v)
		{
			size_t VSize = v.size();
			_start = new T[VSize];
			_finish = _start;
			for (size_t i = 0; i < VSize; i++)
			{
				*_finish++ = v[i];
			}
			_endOfStorage = _finish;
		}

		//        
		vector& operator=(const vector& v)
		{
			if (this != &v)
			{
				size_t VSize = v.size();
				_start = new T[VSize];
				_finish = _start;
				for (int i = 0; i < VSize; i++)
				{
					*_finish++ = v[i];
				}
				_endOfStorage = _finish;
			}
		}

		//  
		~vector()
		{
			if (_start)
			{
				delete[] _start;
				_start = nullptr;
				_finish = nullptr;
				_endOfStorage = nullptr;
			}
		}
		//******************************************************************************
		//   
		//1.     begin
		iterator begin()
		{
			return _start;
		}

		//2.      end
		iterator end()
		{
			return _finish;
		}

		//3.     
		//   rbegin
		reverse_iterator rbegin()
		{
			return end();
		}

		//4.    rend
		reverse_iterator rend()
		{
			return begin();
		}
		//******************************************************************************
		//      
		//1.           
		size_t size()const
		{
			return _finish - _start;
		}

		//2.       
		size_t capacity()const
		{
			return _endOfStorage - _start;
		}

		//3.       
		bool empty()
		{
			return _finish == _start;
		}

		//4.  
		void reserve(size_t NewCapacity)
		{
			size_t OldCapacity = capacity();
			if (NewCapacity > OldCapacity)
			{
				T* temp = new T[NewCapacity];
				size_t OldSize = size();
				if (_start)
				{
					//T:       ? typeid(T).name()
					//      
					//   
					//  :      
					//  :   
					for (size_t i = 0; i < OldSize; i++)
					{
						temp[i] = _start[i];
					}
					//   
					//memcpy  :      :   ,            
					//memcpy(temp, _start, size()*sizeof(T));
					delete[] _start;
				}
				_start = temp;
				_finish = _start + OldSize;
				_endOfStorage = _start + NewCapacity;
			}
		}

		//5.        
		void resize(size_t NewSize, const T& data = T())
		{
			size_t OldSize = size();
			size_t _Capacity = capacity();
			if (NewSize > OldSize)
			{
				if (NewSize > _Capacity)
				{
					reserve(NewSize);
				}
				
				for (size_t i = OldSize; i < NewSize; i++)
				{
					*(_finish++) = data;
				}

			}
			else if (NewSize < OldSize)
			{
				_finish = _start + NewSize;
			}
		}
		//*******************************************************************************
		//      
		//const
		//1.    
		T operator[](size_t index)
		{
			size_t OldSize = size();
			if (index >= OldSize)
			{
				return NULL;
			}
			//assert(index < OldeSize);
			return _start[index];
		}

		const T* operator[](size_t index)const
		{
			size_t OldSize = size();
			if (index >= OldSize)
			{
				return nullptr;
			}
			//assert(index < OldeSize);
			return _start[index];
		}

		//2.      
		T& front()
		{
			return _start[0];
		}

		const T& front()const
		{
			return _start[0];
		}
		//3.      
		T& back()
		{
			return *(_finish - 1);
		}
		const T& back()const
		{
			return *(_finish - 1);
		}
		//********************************************************************************
		//      
		//1.      
		void push_back(const T& data)
		{
			if (_finish == _endOfStorage)
			{
				size_t OldCapacity = capacity();
				reserve(2 * (OldCapacity + 1));
			}
			*(_finish++) = data;
		}

		//2.      
		void pop_back()
		{
			if (_finish == _start)
			{
				return;
			}
			_finish--;
		}

		//iterator
		//3.      
		iterator insert(iterator position, const T& data)
		{
			if (_finish == _endOfStorage)
			{
				size_t OldCapacity = capacity();
				reserve(2 * (OldCapacity + 1));
			}
			size_t OldSize = size();
			if (position <= OldSize)
			{
				for (size_t i = OldSize; i > position; i--)
				{
					_start[i] = _start[i - 1];
				}
				_start[position] = data;
				_finish++;
			}
		}

		//iterator
		//4.      
		iterator erase(iterator position)
		{
			size_t OldSize = size();
			if (position >= OldSize)
			{
				return;
			}
			for (size_t i = position; i < OldSize; i--)
			{
				_start[i] = _start[i + 1];
			}
			_finish--;
		}

	private:
		T* _start;
		T* _finish;
		T* _endOfStorage;
	};
}

//memset      //

//  vector
template
void PrintVector(FirstVector::vector& v)
{
	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;
}

//                
void TestVector()
{
	FirstVector::vector v1;
	FirstVector::vector v2(10, 5);
	int array[] = { 1,2,3,4,5,6,7,8,9,0 };
	FirstVector::vector v3(array, array + sizeof(array) / sizeof(array[0]));

	cout << v1.empty() << endl;
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
	PrintVector(v1);
	v1.resize(6);
	v1.reserve(10);
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;

	cout << v2.empty() << endl;
	cout << v2.size() << endl;
	cout << v2.capacity() << endl;
	PrintVector(v2);
	v2.resize(6);
	v2.reserve(12);
	cout << v2.size() << endl;
	cout << v2.capacity() << endl;


	PrintVector(v3);
	
}

//               
void TestVector1()
{
	FirstVector::vector v1(10, 5);
	FirstVector::vector v2(v1);
	FirstVector::vector v3 = v1;
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
	cout << v2.size() << endl;
	cout << v2.capacity() << endl;
	cout << v3.size() << endl;
	cout << v3.capacity() << endl;
	PrintVector(v1);
	PrintVector(v2);
	PrintVector(v3);
}

//          
void TestVector2()
{
	int array[] = { 1,2,3,4,5,6,7,8,9,0 };
	FirstVector::vector v4(array, array + sizeof(array) / sizeof(array[0]));
	cout << v4[5] << endl;
	cout << v4.front() << endl;
	cout << v4.back() << endl;
	PrintVector(v4);
}

//          
void TestVector3()
{
	FirstVector::vector v5(15, 6);
	cout << v5.size() << endl;
	v5.push_back(8);
	cout << v5.back() << endl;
	cout << v5.size() << endl;

	v5.pop_back();
	cout << v5.back() << endl;
	cout << v5.size() << endl;
	PrintVector(v5);

	//FirstVector::vector::iterator v6(10, 8);
}


//************************************************************************************************
//     :     :  --->    --->          
//          ,             
//1.      (  ,  ,resize,reserve  )
//2.             (erase)
void TestVector5()
{
	vector v{ 1,2,3,4,5 };
	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;
	vector::iterator it = v.begin();
	v.reserve(16);
	it = v.begin();
	cout << "*it = " << *it << endl;
}

void TestVector6()
{
	vector v{ 1,2,3,4,5 };
	for (auto& e : v)
	{
		cout << e << " ";
	}
	cout << endl;
	vector::iterator it = v.begin();
	while (it != v.end())
	{
		//v.erase(it);	
		it = v.erase(it);
		for (auto& e : v)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}
//it = v.erase(it);
//for (auto& e : v)
//{
//	cout << e << " ";
//}
//cout << endl;
int main()
{
	TestVector6();
	system("pause");
	return 0;
}
//********************************************************************************************

浅いコピー:利点:効率が高い.ただし、カスタムオブジェクトでエラーが発生する可能性があるという問題があります.
深度コピー:利点:エラーは発生しません.しかし効率は低い.
したがって、深いコピーを使用するか浅いコピーを使用するかは、状況によって異なり、両者を総合的に使用してもよい.
ジェーン&ソース