// Vecstr.cpp :模拟vector容器,但是仅仅对string有效!
//
#include "stdafx.h"
#include<string>
#include<iostream>
#include<vector>
#include<memory>
#include<utility>
#include<algorithm>
using namespace std;
class VecStr
{
public:
VecStr():elements(nullptr),first_free(nullptr),cap(nullptr) {}
//VecStr(const VecStr &rh):elements(rh.elements),first_free(rh.first_free),cap(rh.cap){}这没有拷贝元素!
VecStr(const VecStr &rh)
{
auto newdata = alloc_n_copy(rh.begin(), rh.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
VecStr operator=(const VecStr &rh)
{
auto data = alloc_n_copy(rh.begin(), rh.end());//拷贝
free(); //释放原对象!alloc申请的两块空间不相同,所以可以释放!
elements = data.first;
first_free = cap = data.second;
return *this;
}
//只有当一个类没有为自己定义任何拷贝控制成员,且类的每个非static数据成员都可以移动,编译器才会自动合成移动构造函数和赋值函数。对于所有内置成员,都含有移动操作!
VecStr(const VecStr &&rh) noexcept:elements(rh.elements),first_free(rh.first_free),cap(rh.cap)
{
elements = first_free = cap = nullptr; //确保原对象不再指向移动后的源!
}
VecStr& operator=(const VecStr &&rh) noexcept
{
if (&rh != this)
{
free(); //释放现有资源
elements = rh.elements;
first_free = rh.first_free;
cap = rh.cap;
elements = first_free = cap = nullptr;
}
return *this;
}
~VecStr() { free(); }
void push_back(const string &s);
size_t size()const { return first_free - elements; }//已经装入的个数!
size_t capacity()const { return cap - elements; } //总可以装下的个数!
string *begin()const { return elements; }
string *end() const { return first_free; }
private:
string *elements;
string *first_free;
string *cap;
static std::allocator<std::string> alloc; //此为声明语句
pair<string*, string*> alloc_n_copy(const string *lh, const string *rh);
void check_n_alloc()
{
if (size() == capacity())
{
reallocate(); //重新分配内存!
}
}
void free();
void reallocate();
};
void VecStr::push_back(const string &s)
{
check_n_alloc();
alloc.construct(first_free++,s); //在first_free处构造字符串s!
}
pair<string*, string*> VecStr::alloc_n_copy(const string *lh, const string *rh)
{
auto data = alloc.allocate(rh - lh); //拷贝lh至rh范围的元素;
return { data,uninitialized_copy(lh,rh,data) };//uninitialized_copy将lh至rh范围内的元素拷贝至data!返回首地址data和尾地址!
}
void VecStr::free()
{
if (elements)
{
for (auto p = first_free; p != elements;)
alloc.destroy(--p);
alloc.deallocate(elements, cap - elements);
}
}
void VecStr::reallocate()
{
auto newcapacity = size() ? 2 * size() : 1;
auto newdata = alloc.allocate(newcapacity);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)//此部分内容可以改为auto dest=uninitialized_copy(make_move_iterator(begin()),make_move_iterator(end()),first) ,返回first_free位置!(make_move_iterator将普通迭代器转为移动迭代器!)
alloc.construct(dest++, std::move(*elem++));
free();//此时释放的什么?
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
}
allocator<std::string> VecStr::alloc;
//静态成员不属于类的任何一个对象,一般来说我们不能在类内部初始化静态成员。相反的,必须在类的外部定义和初始化每个静态成员。和其他对象一样,一个静态成员只能定义一次!
//静态成员在类内初始化只允许static constexpr int period=30;即是在类内初始化了,也需要在类外定义以下该成员constexpr int Account::period!另外,静态成员可以在类中作为函数的实参!
int main()
{
//const vector<string> v = { "string" ,"a"};
allocator<string> a;
auto b1=a.allocate(200);
//a.construct(b1, "asd");
//a.construct(++b1, "adsf");
auto b2 = a.allocate(200);
cout << b1-b2;
return 0;
}
网友评论