在这两篇文件的基础之上;
vector右值引用的push_back方法
修改之前vector代码中的push_back
//
/*void push_back(const T &val)//接收左值
{
if (full())
expand();
_allocator.construct(_last, val);
_last++;
}
void push_back(T &&val)//接收右值 一个右值引用变量本身还是一个左值
{
if (full())
expand();
_allocator.construct(_last, std::move(val));
//val本身还是左值啊。匹配的还是左值的construct。怎么办?
//使用std::move把val 强转成右值引用类型
_last++;
}*/
template<typename Ty>//函数模板的类型推演 + 引用折叠
void push_back(Ty &&val)//
{
if (full())
expand();
//move(左值):移动语义,得到右值类型 (int&&)a
//forward:类型完美转发,能够识别左值和右值类型
_allocator.construct(_last, std::forward<Ty>(val));
_last++;
}
使用void push_back(Ty &&val)为什么可以识别左值和右值呢?
引用重叠:
左值引用+右值引用=左值引用
右值引用+右值引用=右值引用
例如:
push_back(左值引用); 由于接收是Ty &&val;右值引用;左值引用+右值引用=左值引用 最终依然是一个左值引用;
同理右值引用;
通过std::forword可以识别左值和右值
/*void construct(T *p, const T &val)//负责对象构造
{
new (p) T(val); // 定位new
}
void construct(T *p, T &&val)//负责责对象构造
{
new (p) T(std::move(val));
//定位new 强转成右值引用类型 调用底层的T右值引用的拷贝构造函数
}*/
//可以用std::move强转成右值,也可以如下做法:
//无法区分右值和左值的简便的解决办法:
template<typename Ty>
void construct(T *p, Ty &&val)
{
new (p) T(std::forward<Ty>(val));
}
最终代码:
#include <iostream>
//容器的空间配置器
template <typename T>
struct Allocator
{
T* allocate(size_t size)//只负责内存开辟
{
return (T*)malloc(sizeof(T) * size);
}
void deallocate(void *p)//只负责内存释放
{
free(p);
}
template<typename Ty>
void construct(T *p, Ty &&val)
{
new (p) T(std::forward<Ty>(val));
}
void destroy(T *p)//只负责对象析构
{
p->~T();//~T()代表了T类型的析构函数
}
};
template <typename T, typename Alloc = Allocator<T>>
class vector//向量容器
{
public:
vector(int size = 10)//构造
{
//_first = new T[size];
_first = _allocator.allocate(size);
_last = _first;
_end = _first + size;
}
~vector()//析构
{
//delete[]_first;
for (T *p = _first; p != _last; ++p)
{
_allocator.destroy(p);//把_first指针指向的数组的有效元素析构
}
_allocator.deallocate(_first);//释放堆上的数组内存
_first = _last = _end = nullptr;
}
vector(const vector<T> &rhs)//拷贝构造
{
int size = rhs._end - rhs._first;//空间大小
//_first = new T[size];
_first = _allocator.allocate(size);
int len = rhs._last - rhs._first;//有效元素
for (int i = 0; i < len; ++i)
{
//_first[i] = rhs._first[i];
_allocator.construct(_first + i, rhs._first[i]);
}
_last = _first + len;
_end = _first + size;
}
vector<T>& operator=(const vector<T> &rhs)//赋值运算符重载
{
if (this == &rhs)
{
return *this;
}
//delete[]_first;
for (T *p = _first; p != _last; ++p)
{
_allocator.destory(p);//把_first指针指向的数组的有效元素析构
}
_allocator.deallocate(_first);//释放堆上的数组内存
int size = rhs._end - rhs._first;//空间大小
_first = _allocator.allocate(size);
int len = rhs._last - rhs._first;//有效元素
for (int i = 0; i < len; ++i)
{
_allocator.construct(_first + i, rhs._first[i]);
}
_last = _first + len;
_end = _first + size;
return *this;
}
template<typename Ty>//函数模板的类型推演 + 引用折叠
void push_back(Ty &&val)//Ty CMyString& + && = CMyString&
{
if (full())
expand();
//move(左值):移动语义,得到右值类型 (int&&)a
//forward:类型完美转发,能够识别左值和右值类型
_allocator.construct(_last, std::forward<Ty>(val));
_last++;
}
void pop_back()//尾删
{
if (empty()) return;
verify(_last - 1, _last);
//erase(it); verift(it._ptr, _last);
//insert(it,val); verift(it._ptr, _last);
//--_last;
//不仅要把_last指针--,还需要析构删除的元素
--_last;
_allocator.destroy(_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;
}
T& operator[](int index)
{
if (index < 0 || index >= size())
{
throw "OutOfRangeException";
}
return _first[index];
}
//迭代器一般实现成容器的嵌套类型
class iterator
{
public:
friend class vector <T, Alloc>;
//新生成当前容器某一个位置元素的迭代器
iterator(vector<T, Alloc> *pvec = nullptr
, T *ptr = nullptr)
:_ptr(ptr), _pVec(pvec)
{
Iterator_Base *itb = new Iterator_Base(this, _pVec->_head._next);
_pVec->_head._next = itb;
}
bool operator!=(const iterator &it)const
{
//检查迭代器的有效性
if (_pVec == nullptr || _pVec != it._pVec)//迭代器为空或迭代两个不同容器
{
throw "iterator incompatable!";
}
return _ptr != it._ptr;
}
void operator++()
{
//检查迭代器有效性
if (_pVec == nullptr)
{
throw "iterator incalid!";
}
_ptr++;
}
T& operator*()
{
//检查迭代器有效性
if (_pVec == nullptr)
{
throw "iterator invalid!";
}
return *_ptr;
}
const T& operator*()const
{
if (_pVec == nullptr)
{
throw "iterator invalid!";
}
return *_ptr;
}
private:
T *_ptr;
//当前迭代器是哪个容器对象
vector<T, Alloc> *_pVec;//指向当前对象容器的指针
};
iterator begin()
{
return iterator(this, _first);
}
iterator end()
{
return iterator(this, _last);
}
//检查迭代器失效
void verify(T *first, T *last)
{
Iterator_Base *pre = &this->_head;
Iterator_Base *it = this->_head._next;
while (it != nullptr)
{
if (it->_cur->_ptr > first && it->_cur->_ptr <= last)
{
//迭代器失效,把iterator持有的容器指针置nullptr
it->_cur->_pVec = nullptr;
//删除当前迭代器节点,继续判断后面的迭代器节点是否失效
pre->_next = it->_next;
delete it;
it = pre->_next;
}
else
{
pre = it;
it = it->_next;
}
}
}
//自定义vector容器insert方法实现
iterator insert(iterator it, const T &val)
{
//1.这里我们未考虑扩容
//2.还未考虑it._ptr指针合法性,假设它合法
verify(it._ptr - 1, _last);
T *p = _last;
while (p > it._ptr)
{
_allocator.construct(p, *(p - 1));
_allocator.destroy(p - 1);
p--;
}
_allocator.construct(p, val);
_last++;
return iterator(this, p);
}
//自定义vector容器erase方法实现
iterator erase(iterator it)
{
verify(it._ptr - 1, _last);
T *p = it._ptr;
while (p < _last - 1)
{
_allocator.destroy(p);
_allocator.construct(p, *(p + 1));
p++;
}
_allocator.destroy(p);
_last--;
return iterator(this, it._ptr);
}
private:
T *_first;//起始数组位置
T *_last;//指向最后一个有效元素后继位置
T *_end;//指向数组空间的后继位置
Alloc _allocator;//定义容器的空间配置器对象
//容器迭代器失效增加代码
struct Iterator_Base
{
Iterator_Base(iterator *c = nullptr, Iterator_Base *n = nullptr)
:_cur(c), _next(n) {}
iterator *_cur;
Iterator_Base *_next;
};
Iterator_Base _head;
void expand()//扩容
{
int size = _end - _first;
//T *ptmp = new T[2*size];
T *ptmp = _allocator.allocate(2 * size);
for (int i = 0; i < size; ++i)
{
_allocator.construct(ptmp + i, _first[i]);
//ptmp[i] = _first[i];
}
//delete[]_first;
for (T *p = _first; p != _last; ++p)
{
_allocator.destroy(p);
}
_allocator.deallocate(_first);
_first = ptmp;
_last = _first + size;
_end = _first + 2 * size;
}
};
#include <iostream>
using namespace std;
class Test
{
public:
Test(int a = 10) :ma(a)
{
cout << "Test(int)" << endl;
}
~Test()
{
cout << "~Test()" << endl;
}
Test(const Test &t) :ma(t.ma)
{
cout << "Test(const Test&)" << endl;
}
Test(Test &&t) :ma(t.ma)
{
cout << "Test(const Test&&)" << endl;
}
Test& operator=(const Test &t)
{
cout << "operator=(const Test &t)" << endl;
ma = t.ma;
return *this;
}
Test& operator=(Test &&t)
{
cout << "operator=((Test &&t)" << endl;
ma = t.ma;
return *this;
}
private:
int ma;
};
int main()
{
Test t1;
std::cout << "---------------begin\n";
vector<Test> v;
v.push_back(t1);
v.push_back(Test(123));
std::cout << "---------------end\n";
return 0;
}
move和forword的实现
std::move的底层实现
// FUNCTION TEMPLATE move
template<class _Ty>
_NODISCARD constexpr remove_reference_t<_Ty>&&
move(_Ty&& _Arg) noexcept
{ // forward _Arg as movable
return (static_cast<remove_reference_t<_Ty>&&>(_Arg));
}
static_cast显示将一个左值转换为一个右值引用
std::forward的底层实现
// FUNCTION TEMPLATE forward
template<class _Ty>
_NODISCARD constexpr _Ty&& forward(remove_reference_t<_Ty>& _Arg) noexcept
{ // forward an lvalue as either an lvalue or an rvalue
return (static_cast<_Ty&&>(_Arg));
}
template<class _Ty>
_NODISCARD constexpr _Ty&& forward(remove_reference_t<_Ty>&& _Arg) noexcept
{ // forward an rvalue as an rvalue
static_assert(!is_lvalue_reference_v<_Ty>, "bad forward call");
return (static_cast<_Ty&&>(_Arg));
}
对左值引用和右值引用分别使用不同的模板函数,都返回了 static_cast<_Ty&&>(_Arg)