C++ Primer 5th笔记(chap 13 拷贝控制) 实例2内存管理
生活随笔
收集整理的這篇文章主要介紹了
C++ Primer 5th笔记(chap 13 拷贝控制) 实例2内存管理
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1. 目標(biāo)
實(shí)現(xiàn)標(biāo)準(zhǔn)庫vector類的一個(gè)簡化版本,只支持string,我們命名為StrVec。
2. 設(shè)計(jì)思想
2.1 allocator管理每個(gè)StrVec對(duì)象的內(nèi)存池, 是一塊連續(xù)的內(nèi)存(類型為元素的數(shù)組)。用于構(gòu)建存儲(chǔ)插入的元素
push_back插入元素, 檢查內(nèi)存池是否夠用?. 夠用,在內(nèi)存池的下—可用位置構(gòu)造對(duì)象·. 不夠用,重組空間: . allocator獲取全新的更大的內(nèi)存池. 將已有元素拷貝至新的內(nèi)存池. 釋放舊的內(nèi)存池. 在新內(nèi)存池的下—可用位置構(gòu)造新加入的元素2.2 四個(gè)工具函數(shù):
alloc_n_copy 會(huì)分配內(nèi)存,并拷貝一個(gè)給定范圍中的元素。
free 會(huì)銷毀構(gòu)造元素并釋放內(nèi)存。
chk_n_alloc 保證 StrVec 至少有容納一個(gè)新元素的空間,如果沒有空間添加新元素,chk_n_alloc 會(huì)調(diào)用 reallocate 類分配更多的內(nèi)存。
reallocate 在內(nèi)存用完時(shí)為 StrVec 分配新的內(nèi)存。
3. StrVec.h
class StrVec { public:// copy control membersStrVec(): elements(nullptr), first_free(nullptr), cap(nullptr) { }StrVec(const StrVec&); // copy constructorStrVec &operator=(const StrVec&); // copy assignment#ifdef NOEXCEPTStrVec(StrVec&&) noexcept; // move constructorStrVec &operator=(StrVec&&) noexcept; // move assignment~StrVec() noexcept; // destructor #elseStrVec(StrVec&&) throw(); // move constructorStrVec &operator=(StrVec&&) throw(); // move assignment~StrVec() throw(); // destructor #endif#ifdef INIT_LIST// additional constructorStrVec(std::initializer_list<std::string>); #else // define a constructor that takes pointers to a range of elementsStrVec(const std::string*, const std::string*); #endifvoid push_back(const std::string&); // copy the elementvoid push_back(std::string&&); // move the element// add elementssize_t size() const { return first_free - elements; }size_t capacity() const { return cap - elements; }// iterator interfacestd::string *begin() const { return elements; }std::string *end() const { return first_free; }#ifdef INIT_LIST // no real substitute for initializer_list in assignments// operator functions covered in chapter 14StrVec &operator=(std::initializer_list<std::string>); #endifstd::string& operator[](std::size_t n) { return elements[n]; }const std::string& operator[](std::size_t n) const { return elements[n]; }#ifdef VARIADICS // no direct substitute for variadic functions// emplace member covered in chapter 16template <class... Args> void emplace_back(Args&&...); #endif private:static std::allocator<std::string> alloc; // allocates the elements// utility functions:// used by members that add elements to the StrVecvoid chk_n_alloc() { if (size() == capacity()) reallocate(); }// used by the copy constructor, assignment operator, and destructorstd::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);void free(); // destroy the elements and free the spacevoid reallocate(); // get more space and copy the existing elementsstd::string *elements; // pointer to the first element in the arraystd::string *first_free; // pointer to the first free element in the arraystd::string *cap; // pointer to one past the end of the array };#include <algorithm>inline #ifdef NOEXCEPT StrVec::~StrVec() noexcept { free(); } #else StrVec::~StrVec() throw() { free(); } #endif4. StrVec.cpp
inline std::pair<std::string*, std::string*> StrVec::alloc_n_copy(const std::string *b, const std::string *e) {// allocate space to hold as many elements as are in the rangeauto data = alloc.allocate(e - b); // initialize and return a pair constructed from data and// the value returned by uninitialized_copy #ifdef LIST_INITreturn {data, uninitialized_copy(b, e, data)}; #elsereturn make_pair(data, uninitialized_copy(b, e, data)); #endif }inline #ifdef NOEXCEPT StrVec::StrVec(StrVec &&s) noexcept // move won't throw any exceptions #else StrVec::StrVec(StrVec &&s) throw() // move won't throw any exceptions #endif// member initializers take over the resources in s: elements(s.elements), first_free(s.first_free), cap(s.cap) {// leave s in a state in which it is safe to run the destructors.elements = s.first_free = s.cap = nullptr; }inline StrVec::StrVec(const StrVec &s) {// call alloc_n_copy to allocate exactly as many elements as in sauto newdata = alloc_n_copy(s.begin(), s.end());elements = newdata.first; first_free = cap = newdata.second; }inline void StrVec::free() {// may not pass deallocate a 0 pointer; if elements is 0, there's no work to doif (elements) {// destroy the old elements in reverse orderfor (auto p = first_free; p != elements; /* empty */)alloc.destroy(--p); alloc.deallocate(elements, cap - elements);} }#ifdef INIT_LIST inline StrVec &StrVec::operator=(std::initializer_list<std::string> il) {// alloc_n_copy allocates space and copies elements from the given rangeauto data = alloc_n_copy(il.begin(), il.end());free(); // destroy the elements in this object and free the spaceelements = data.first; // update data members to point to the new spacefirst_free = cap = data.second;return *this; } #endif inline #ifdef NOEXCEPT StrVec &StrVec::operator=(StrVec &&rhs) noexcept #else StrVec &StrVec::operator=(StrVec &&rhs) throw() #endif {// direct test for self-assignmentif (this != &rhs) {free(); // free existing elements elements = rhs.elements; // take over resources from rhsfirst_free = rhs.first_free;cap = rhs.cap;// leave rhs in a destructible staterhs.elements = rhs.first_free = rhs.cap = nullptr;}return *this; }inline StrVec &StrVec::operator=(const StrVec &rhs) {// call alloc_n_copy to allocate exactly as many elements as in rhsauto data = alloc_n_copy(rhs.begin(), rhs.end());free();elements = data.first;first_free = cap = data.second;return *this; }inline void StrVec::reallocate() {// we'll allocate space for twice as many elements as the current sizeauto newcapacity = size() ? 2 * size() : 1;// allocate new memoryauto newdata = alloc.allocate(newcapacity);// move the data from the old memory to the newauto dest = newdata; // points to the next free position in the new arrayauto elem = elements; // points to the next element in the old arrayfor (size_t i = 0; i != size(); ++i)alloc.construct(dest++, std::move(*elem++));free(); // free the old space once we've moved the elements// update our data structure to point to the new elementselements = newdata;first_free = dest;cap = elements + newcapacity; }#ifdef INIT_LIST inline StrVec::StrVec(std::initializer_list<std::string> il) {// call alloc_n_copy to allocate exactly as many elements as in ilauto newdata = alloc_n_copy(il.begin(), il.end());elements = newdata.first;first_free = cap = newdata.second; } #else inline StrVec::StrVec(const std::string *b, const std::string* e) {// call alloc_n_copy to allocate exactly as many elements as in the rangeauto newdata = alloc_n_copy(b, e);elements = newdata.first;first_free = cap = newdata.second; } #endifinline void StrVec::push_back(const std::string& s) {chk_n_alloc(); // ensure that there is room for another element// construct a copy of s in the element to which first_free pointsalloc.construct(first_free++, s); }inline void StrVec::push_back(std::string &&s) {chk_n_alloc(); // reallocates the StrVec if necessaryalloc.construct(first_free++, std::move(s)); }#ifdef VARIADICS // no direct substitute for variadic functions // emplace member covered in chapter 16 template <class... Args> inline void StrVec::emplace_back(Args&&... args) {chk_n_alloc(); // reallocates the StrVec if necessaryalloc.construct(first_free++, std::forward<Args>(args)...); } #endif#endif【參考】
[1] 代碼StrVec.h
總結(jié)
以上是生活随笔為你收集整理的C++ Primer 5th笔记(chap 13 拷贝控制) 实例2内存管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ Primer 5th笔记(cha
- 下一篇: C++ Primer 5th笔记(cha