C++?vector的簡單實(shí)現(xiàn)
向量
向量是序列容器,表示可以更改大小的數(shù)組。
就像數(shù)組一樣,向量對(duì)其元素使用連續(xù)的存儲(chǔ)位置,這意味著也可以使用指向其元素的常規(guī)指針上的偏移量來訪問其元素,并且與數(shù)組一樣高效。但與數(shù)組不同的是,它們的大小可以動(dòng)態(tài)變化,它們的存儲(chǔ)由容器自動(dòng)處理。
在內(nèi)部,向量使用動(dòng)態(tài)分配的數(shù)組來存儲(chǔ)其元素??赡苄枰匦路峙浯藬?shù)組,以便在插入新元素時(shí)增加大小,這意味著分配新數(shù)組并將所有元素移動(dòng)到該數(shù)組。就處理時(shí)間而言,這是一項(xiàng)相對(duì)昂貴的任務(wù),因此,每次將元素添加到容器時(shí),向量都不會(huì)重新分配。
相反,向量容器可以分配一些額外的存儲(chǔ)以適應(yīng)可能的增長,因此容器的實(shí)際容量可能大于嚴(yán)格需要的存儲(chǔ)來包含其元素(即其大?。炜梢詫?shí)現(xiàn)不同的增長策略,以平衡內(nèi)存使用和重新分配,但無論如何,重新分配應(yīng)僅以對(duì)數(shù)增長的大小間隔發(fā)生,以便可以在向量末尾插入單個(gè)元素,并提供攤銷的恒定時(shí)間復(fù)雜性。
因此,與數(shù)組相比,向量消耗更多的內(nèi)存,以換取管理存儲(chǔ)和以有效方式動(dòng)態(tài)增長的能力。
與其他動(dòng)態(tài)序列容器(deques、list 和 forward_lists)相比,向量非常有效地訪問其元素(就像數(shù)組一樣),并且相對(duì)有效地從其末尾添加或刪除元素。對(duì)于涉及在末尾以外的位置插入或刪除元素的操作,它們的性能比其他元素差,并且迭代器和引用的一致性低于 lists 和 forward_lists。
成員函數(shù)
(構(gòu)造函數(shù)) 構(gòu)造 vector(公開成員函數(shù)) (析構(gòu)函數(shù)) 析構(gòu) vector(公開成員函數(shù)) operator= 賦值給容器(公開成員函數(shù)) assign 將值賦給容器(公開成員函數(shù)) get_allocator 返回相關(guān)的分配器(公開成員函數(shù)) 元素訪問 at 訪問指定的元素,同時(shí)進(jìn)行越界檢查(公開成員函數(shù)) operator[] 訪問指定的元素(公開成員函數(shù)) front 訪問第一個(gè)元素(公開成員函數(shù)) back 訪問最后一個(gè)元素(公開成員函數(shù)) data 直接訪問底層數(shù)組(公開成員函數(shù)) 迭代器 begin,cbegin(C++11) 返回指向起始的迭代器(公開成員函數(shù)) end,cend(C++11) 返回指向末尾的迭代器(公開成員函數(shù)) rbegin,crbegin(C++11) 返回指向起始的逆向迭代器(公開成員函數(shù)) rend,crend(C++11) 返回指向末尾的逆向迭代器(公開成員函數(shù)) 容量 empty 檢查容器是否為空(公開成員函數(shù)) size 返回容納的元素?cái)?shù)(公開成員函數(shù)) max_size 返回可容納的最大元素?cái)?shù)(公開成員函數(shù)) reserve 預(yù)留存儲(chǔ)空間(公開成員函數(shù)) capacity 返回當(dāng)前存儲(chǔ)空間能夠容納的元素?cái)?shù)(公開成員函數(shù)) shrink_to_fit(C++11) 通過釋放未使用的內(nèi)存減少內(nèi)存的使用(公開成員函數(shù)) 修改器 clear 清除內(nèi)容(公開成員函數(shù)) insert 插入元素(公開成員函數(shù)) emplace(C++11) 原位構(gòu)造元素(公開成員函數(shù)) erase 擦除元素(公開成員函數(shù)) push_back 將元素添加到容器末尾(公開成員函數(shù)) emplace_back(C++11) 在容器末尾就地構(gòu)造元素(公開成員函數(shù)) pop_back 移除末元素(公開成員函數(shù)) resize 改變?nèi)萜髦锌纱鎯?chǔ)元素的個(gè)數(shù)(公開成員函數(shù)) swap 交換內(nèi)容(公開成員函數(shù)) 非成員函數(shù) 按照字典順序比較 vector 中的值(函數(shù)模板) operator== operator!=(C++20 中移除) operator<(C++20 中移除) operator<=(C++20 中移除) operator>(C++20 中移除) operator>=(C++20 中移除) operator<=>(C++20) std::swap(std::vector) 特化 std::swap 算法(函數(shù)模板) erase(std::vector),erase_if(std::vector) (C++20) 擦除所有滿足特定判別標(biāo)準(zhǔn)的元素(函數(shù)模板
cpp
template <typename T> class Vector { public: Vector() noexcept = default; explicit Vector(size_t n) : cap_{n}, ptr_{alloc(cap_)} { for (; len_ < n; ++len_) { construct(ptr_ + len_); //調(diào)用T的默認(rèn)構(gòu)造 } } Vector(size_t n, const T &x) : cap_{n}, ptr_{alloc(cap_)} { for (; len_ < n; ++len_) { construct(ptr_ + len_, x); //調(diào)用T的拷貝構(gòu)造 } } Vector(const Vector &x) : cap_{x.size()}, ptr_{alloc(cap_)} //拷貝構(gòu)造 { for (; len_ < x.size(); ++len_) { construct(ptr_ + len_, x[len_]); } } Vector(Vector &&x) noexcept //移動(dòng)構(gòu)造 { cap_ = std::__exchange(x.cap_, 0); len_ = std::__exchange(x.len_, 0); ptr_ = std::__exchange(x.ptr_, nullptr); } Vector(std::initializer_list<T> li) : cap_{li.size()}, ptr_{alloc(cap_)} //初始化列表 { for (auto &x : li) { construct(ptr_ + len_, x); ++len_; } } ~Vector() noexcept { clear(); dealloc(ptr_); } void swap(Vector &x) noexcept { using std::swap; // ADL swap(cap_, x.cap_); swap(len_, x.len_); swap(ptr_, x.ptr_); } void clear() noexcept { for (; len_ > 0; --len_) { destroy(ptr_ + len_ - 1); } } Vector &operator=(const T &x) //拷貝賦值 { if (this != &x) { Vector{x}.swap(*this); } return *this; } Vector &operator=(T &&x) noexcept //移動(dòng)賦值 { if (this != &x) { Vector{std::move(x)}.swap(*this); } return *this; } Vector &operator=(std::initializer_list<T> li) //初始化列表賦值 { Vector{li}.swap(*this); return *this; } void push_back(const T &x) //拷貝 { emplace_back(x); } void push_back(T &&x) //移動(dòng) { emplace_back(x); } template <typename... Args> void emplace_back(Args &&...args) //直接傳遞構(gòu)造函數(shù) { if (len_ == cap_) { size_t new_cap = cap_ ? cap_ * 2 : 1; //等0返回1 T *new_ptr = alloc(new_cap); for (size_t new_len; new_len < len_; ++new_len) { construct(new_ptr + new_len, std::move_if_noexcept(ptr_[new_len])); } cap_ = new_cap; ptr_ = new_ptr; } construct(ptr_ + len_, std::forward<Args>(args)...); ++len_; } void pop_back() noexcept { if (len_ < cap_ / 2) { size_t new_cap = cap_ / 2; T *new_ptr = alloc(new_cap); for (size_t new_len = 0; new_len < len_; ++new_len) { construct(new_ptr + new_len, std::move_if_noexcept(ptr_[new_len])); } cap_ = new_cap; ptr_ = new_ptr; } destroy(ptr_ + len_ - 1); --len_; } size_t size() const noexcept { return len_; } size_t capacity() const noexcept { return cap_; } bool empty() const noexcept { return len_ == 0; } T &operator[](size_t i) { return ptr_[i]; } const T &operator[](size_t i) const { return ptr_[i]; } T *begin() noexcept { return ptr_; } T *end() noexcept { return ptr_ + len_; } const T *begin() const noexcept { return ptr_; } const T *end() const noexcept { return ptr_ + len_; } private: T *alloc(size_t n) //分配n個(gè)大小內(nèi)存 { return static_cast<T *>(::operator new(sizeof(T) * n)); } void dealloc(T *p) noexcept //釋放內(nèi)存 { ::operator delete(p); } template <typename... Args> void construct(T *p, Args &&...args) //在這塊內(nèi)存上構(gòu)造T類型對(duì)象 { ::new (p) T(std::forward<Args>(args)...); } void destroy(T *p) noexcept { p->~T(); } private: size_t cap_{0}; //容量 size_t len_{0}; //元素個(gè)數(shù) T *ptr_{nullptr}; };
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C++學(xué)習(xí)之智能指針中的unique_ptr與shared_ptr
吃獨(dú)食的unique_ptr與樂于分享的shared_ptr是C++中常見的兩個(gè)智能指針,本文主要為大家介紹了這兩個(gè)指針的使用以及智能指針使用的原因,希望對(duì)大家有所幫助2023-05-05Matlab實(shí)現(xiàn)別踩白塊小游戲的示例代碼
別踩白塊是一款音樂類休閑游戲,游戲的玩法不難,只需跟著音樂的節(jié)奏點(diǎn)中對(duì)的方塊即可。本文將用Matlab實(shí)現(xiàn)這一經(jīng)典游戲,感興趣的可以了解一下2022-03-03C語言中的long型究竟占4個(gè)字節(jié)還是8個(gè)字節(jié)(遇到的坑)
小編在復(fù)習(xí)C語言的時(shí)候踩到了不少坑,糾結(jié)long類型究竟占4個(gè)字節(jié)還是8個(gè)字節(jié)呢?好,今天通過本文給大家分享下我的詳細(xì)思路,感興趣的朋友跟隨小編一起看看吧2021-11-11C語言鏈表實(shí)現(xiàn)商品庫存管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語言鏈表實(shí)現(xiàn)商品庫存管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02C語言經(jīng)典例程100例(經(jīng)典c程序100例)
這篇文章主要介紹了C語言經(jīng)典例程100例,經(jīng)典c程序100例,學(xué)習(xí)c語言的朋友可以參考一下2018-03-03C++實(shí)現(xiàn)棧的操作(push和pop)
這篇文章主要介紹了C++實(shí)現(xiàn)棧的操作(push和pop),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07