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