動態記憶體管理allocator類C++ STL標準模板庫vector實現
阿新 • • 發佈:2018-12-11
//vector.h
#ifndef NSTL_VECTOR_H_
#define NSTL_VECTOR_H_
#include <memory>
#include <string>
namespace nstl {
class vector {
public:
vector() : elements(nullptr), first_free(nullptr), cap(nullptr) {
}
vector(const vector&);
vector& operator= (const vector&);
~ vector();
void push_back(const std::string&);
size_t size() const {
return first_free - elements;
}
size_t capacity() const {
return cap - elements;
}
std::string* begin() const {
return elements;
}
std::string* end() const {
return first_free;
}
private:
static std:: allocator<std::string> alloc;
void chk_n_alloc() {
if (size() == capacity()) {
reallocate();
}
}
std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);
void free();
void reallocate();
std::string* elements;
std::string* first_free;
std::string* cap;
};
}
#endif
//vector.cpp
#include "vector.h"
using namespace nstl;
std::allocator<std::string> vector::alloc;
vector::vector(const vector& str) {
auto data = alloc_n_copy(str.begin(), str.end());
elements = data.first;
first_free = cap = data.second;
}
vector::~vector() {
free();
}
vector& vector::operator= (const vector& str) {
auto data = alloc_n_copy(str.begin(), str.end());
free();
elements = data.first;
first_free = cap = data.second;
return *this;
}
void vector::push_back(const std::string& str) {
chk_n_alloc();
alloc.construct(first_free++, str);
}
std::pair<std::string*, std::string*> vector::alloc_n_copy(const std::string* begin, const std::string* end) {
auto data = alloc.allocate(end - begin);
//warning C4996: Call to 'std::uninitialized_copy' with parameters that may be unsafe
return{ data, std::uninitialized_copy(begin, end, data) };
}
void vector::free() {
if (elements) {
for (auto p = first_free; p != elements; ) {
alloc.destroy(--p);
}
alloc.deallocate(elements, cap - elements);
}
}
void vector::reallocate() {
auto capacity = size() ? 2 * size() : 1;
auto data = alloc.allocate(capacity);
auto databak = data;
auto elembak = elements;
for (size_t i = 0; i != size(); ++i) {
//using std::move(string,don't copy construct)
alloc.construct(databak++, std::move(*elembak++));
}
free(); //need elemets, no destructor string
elements = data;
first_free = databak;
cap = elements + capacity;
}
2018-12-2 於 北京 海淀
References:
C++ Primer(第五版)