一:动态内存管理
allocator类:
/* 拷贝元素 */
void StrVer::push_back(const string& s) {
chk_n_alloc(); //确保有空间容纳新元素
alloc.construct(first_free++,s); //拷贝元素并指向下一个地址
}
/* 内存释放 */
void StrVer::free() {
if (elements) { //如果没有分配空间则不执行(首地址无指针)
for (auto p = first_free; p != elements; --p) { //从空闲的第一个到首地址
alloc.destroy(p); //销毁元素
}
alloc.deallocate(begin(), size()); //释放空间
}
}
allocator算法
/* 内存分配 */
pair<string*, string*>
StrVer::alloc_n_copy(const string* b, const string* e) {
string* data = alloc.allocate(e - b); //分配能容纳给定元素的空间(返回首地址)
return { data,uninitialized_copy(b,e,data) }; //返回一个pair(首地址,尾地址)
}
整体代码示例:
class StrVer {
public:
StrVer() :first_free(nullptr), elements(nullptr), cap(nullptr) {};
StrVer(const StrVer&);
StrVer& operator==(const StrVer&);
~StrVer() { free(); };
void push_back(const string&); //拷贝元素
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:
allocator<string> alloc; // 被添加的元素所使用(这里测试后不能加static不知道为什么)
void chk_n_alloc() { //保证至少有一个容纳新元素的空间
if (size() == capacity()) reallocate();
}
pair<string*, string*> alloc_n_copy(const string*,const string*); //内存分配
void free(); //销毁元素并释放内存
void reallocate(); //获得跟多内存拷贝已有元素
string* elements; //元素首地址
string* first_free; //元素第一个空闲指针
string* cap; //元素尾地址
};
/* 拷贝元素 */
void StrVer::push_back(const string& s) {
chk_n_alloc(); //确保有空间容纳新元素
alloc.construct(first_free++,s); //拷贝元素并指向下一个地址
}
/* 内存分配 */
pair<string*, string*>
StrVer::alloc_n_copy(const string* b, const string* e) {
string* data = alloc.allocate(e - b); //分配能容纳给定元素的空间(返回首地址)
return { data,uninitialized_copy(b,e,data) }; //返回一个pair(首地址,尾地址)
}
/* 内存释放 */
void StrVer::free() {
if (elements) { //如果没有分配空间则不执行(首地址无指针)
for (auto p = first_free; p != elements; --p) { //从空闲的第一个到首地址
alloc.destroy(p); //销毁元素
}
alloc.deallocate(begin(), size()); //释放空间
}
}
/* 拷贝构造函数 */
StrVer::StrVer(const StrVer& s) {
pair<string*, string*> newdata = alloc_n_copy(s.begin(), s.end()); //分配同样多的内存空间
elements = newdata.first; //首地址
first_free = cap = newdata.second; //尾地址和当前地址
};
/* 重载赋值 */
StrVer& StrVer::operator==(const StrVer& rhs) {
free(); //释放当前内存
pair<string*, string*> newdata = alloc_n_copy(s.begin(), s.end()); //分配同样多的内存空间
elements = newdata.first; //首地址
first_free = cap = newdata.second; //尾地址和当前地址
return *this;
}
/* 获得跟多内存拷贝已有元素 */
void StrVer::reallocate(){
size_t newcapacity = size() ? 2 * size() : 1; //双倍空间或者申请空间
string* newdata = alloc.allocate(newcapacity); //申请新空间
string* dest = newdata; //新空间首地址
string* elem = elements; //旧空间首地址
for (size_t i = 0; i != size(); i++) {
alloc.construct(dest++, std::move(*elem++)); //拷贝
}
free(); //释放就内存
/* 更新数据 */
elements = newdata;
first_free = dest;
cap = newdata + newcapacity;
}
二: 对象移动与左右值
/* 移动构造 */
/* 移动构造 */
StrVer::StrVer(StrVer&& rhs) noexcept {
free();
elements = rhs.elements;
first_free = rhs.first_free;
cap = rhs.cap;
rhs.elements = rhs.first_free = rhs.cap = nullptr;
}
/* 移动赋值 */
StrVer& StrVer::operator=(StrVer&& rhs) noexcept {
if (this != &rhs) {
free();
elements = rhs.elements;
first_free = rhs.first_free;
cap = rhs.cap;
rhs.elements = rhs.first_free = rhs.cap = nullptr;
}
return* this;
}
在主程序中使用:
int main()
{
StrVer p1,p2,p3;
p1.push_back("123456"); //写入数据
p2 = p1; //调用拷贝赋值函数
p3 = move(p2); //调用移动赋值函数
return 0;
}