日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++ vector拷贝构造_vector------stl学习笔记一

發布時間:2024/2/28 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++ vector拷贝构造_vector------stl学习笔记一 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

vector其中一個特點:內存空間只會增長,不會減小

援引C++ Primer:為了支持快速的隨機訪問,vector容器的元素以連續方式存放,每一個元素都緊挨著前一個元素存儲。

設想一下,當vector添加一個元素時,為了滿足連續存放這個特性,都需要重新分配空間、拷貝元素、撤銷舊空間,這樣性能難以接受。因此STL實現者在對vector進行內存分配時,其實際分配的容量要比當前所需的空間多一些。就是說,vector容器預留了一些額外的存儲區,用于存放新添加的元素,這樣就不必為每個新元素重新分配整個容器的內存空間。

原文:https://www.cnblogs.com/biyeymyhjob/archive/2012/09/12/2674004.html


push_back復雜度O(1),插入最壞情況的復雜度為O(n)。

不需要在其他位置插入元素,需要隨機訪問,用vector是比較不錯的。

要是有時候需要中間和其他位置的插入和刪除,那么list可能是個不錯的選擇。


push_back發生了什么

#include <iostream> #include <vector>class Point {public:Point(){std::cout<<"construction is called"<<std::endl;}Point(const Point& p){std::cout<<"copy construction is called"<<std::endl;}~Point(){std::cout<<"destruction is called"<<std::endl;} };int main() {std::vector<Point> pointVec;Point a;Point b;pointVec.push_back(a);pointVec.push_back(b);std::cout<<pointVec.size()<<std::endl;return 0; }

其中執行

pointVec.push_back(a);

此時vector會申請一個內存空間,并調用拷貝構造函數將a放到vector中

再調用

pointVec.push_back(b);

此時內存不夠 需要擴大內存,重新分配內存 這時再調用拷貝構造函數將a拷貝到新的內存,再將b拷入新的內存(所以拷貝構造函數調用了三次),緊接著將原來的vector的內存釋放所以調用一次析構函數釋放a,然后函數結束,pointVec(含有a和b)和最初的a,b兩個對象被釋放,所以調用四次析構函數


拷貝構造函數的調用時機

  • 當函數的參數為類的對象時(這是引用 :Book &book 這是對象:Book book)
  • 函數的返回值是類的對象(不是引用)
  • 對象需要通過另外一個對象進行初始化

vector是怎么擴大容量的

現在改一下上面的main函數

int main() {std::vector<Point> pointVec;Point a;Point b;pointVec.push_back(a);std::cout<<"size="<<pointVec.size()<<std::endl;std::cout<<"capacity="<<pointVec.capacity()<<std::endl;pointVec.push_back(b);std::cout<<"size="<<pointVec.size()<<std::endl;std::cout<<"capacity="<<pointVec.capacity()<<std::endl;pointVec.push_back(b);pointVec.push_back(a);std::cout<<"size="<<pointVec.size()<<std::endl;std::cout<<"capacity="<<pointVec.capacity()<<std::endl;pointVec.push_back(b); std::cout<<"size="<<pointVec.size()<<std::endl;std::cout<<"capacity="<<pointVec.capacity()<<std::endl;return 0; }

下面使是輸出內容 目的是為了看一下vector怎么分配內存的(注意capacity()容器的容量不等于size())

每次超出 vector都會擴大一倍容量

$ ./test construction is called construction is called copy construction is called size=1 capacity=1 copy construction is called copy construction is called destruction is called size=2 capacity=2 copy construction is called copy construction is called copy construction is called destruction is called destruction is called copy construction is called size=4 capacity=4 copy construction is called copy construction is called copy construction is called copy construction is called copy construction is called destruction is called destruction is called destruction is called destruction is called size=5 capacity=8 destruction is called destruction is called destruction is called destruction is called destruction is called destruction is called destruction is called

在引入右值引用,轉移構造函數,轉移復制運算符之前,通常使用push_back()向容器中加入一個右值元素(臨時對象)的時候,首先會調用構造函數構造這個臨時對象,然后需要調用拷貝構造函數將這個臨時對象放入容器中。原來的臨時變量釋放。這樣造成的問題是臨時變量申請的資源就浪費。

原文:https://blog.csdn.net/MOU_IT/article/details/88757348


vector emplace_back和push_back()區別

臨時對象創建的時候用emplace_back和push_back()有區別,如果是下面這樣則沒有區別

#include <iostream> #include <vector>class Point {public:Point(){std::cout<<"construction is called"<<std::endl;}Point(const Point& p){std::cout<<"copy construction is called"<<std::endl;}Point(Point&& ohter){ std::cout<<"moveConstruction is called"<<std::endl;} };int main() {std::vector<Point> pointVec1;std::vector<Point> pointVec2;Point a;Point b;std::cout<<"push_back(a):"<<std::endl;pointVec1.push_back(a);std::cout<<"emplace_back(a):"<<std::endl;pointVec2.emplace_back(a);std::cout<<"return 0;"<<std::endl;return 0; }

輸出 可以看出這么做并沒有區別

$ ./test construction is called construction is called push_back(a): copy construction is called emplace_back(a): copy construction is called return 0;

而這樣 則會有區別:

#include <iostream> #include <vector> #include <string>class Point {public:Point(std::string name,int price) :name_(name), price_(price){std::cout<<"construction is called"<<std::endl;}Point(const Point& other):name_(other.name_), price_(other.price_){std::cout<<"copy construction is called"<<std::endl;}Point(Point&& other):name_(other.name_), price_(other.price_){std::cout<<"moveConstruction is called"<<std::endl;}public:std::string name_;int price_; };int main() {std::vector<Point> pointVec1;std::vector<Point> pointVec2;std::cout<<"push_back:"<<std::endl;pointVec1.push_back(Point("banana",13));std::cout<<"emplace_back:"<<std::endl;pointVec2.emplace_back("apple",14);//注意pusk_back不可以這么用std::cout<<"return 0;"<<std::endl;return 0; }

輸出:

$ ./test push_back: construction is called moveConstruction is called emplace_back: construction is called return 0;

總結:

push_back()右值時就會調用構造函數和轉移構造函數。進一步優化的空間就是使用emplace_back,在容器尾部添加一個元素,這個元素原地構造,不需要觸發拷貝構造和轉移構造


std::move()

C++ 標準庫使用比如vector::push_back 等這類函數時,會對參數的對象進行復制,連數據也會復制.這就會造成對象內存的額外創建, 本來原意是想把參數push_back進去就行了,通過std::move,可以避免不必要的拷貝操作。

在C++11中,標準庫在<utility>中提供了一個有用的函數std::move,std::move并不能移動任何東西,它唯一的功能是將一個左值強制轉化為右值引用,繼而可以通過右值引用使用該值,以用于移動語義。從實現上講,std::move基本等同于一個類型轉換:static_cast<T&&>(lvalue);

std::move函數可以以非常簡單的方式將左值引用轉換為右值引用。

std::move是將對象的狀態或者所有權從一個對象轉移到另一個對象,只是轉移,沒有內存的搬遷或者內存拷貝所以可以提高利用效率,改善性能.。

//摘自https://zh.cppreference.com/w/cpp/utility/move #include <iostream> #include <utility> #include <vector> #include <string> int main() {std::string str = "Hello";std::vector<std::string> v;//調用常規的拷貝構造函數,新建字符數組,拷貝數據v.push_back(str);std::cout << "After copy, str is "" << str << ""n";//調用移動構造函數,掏空str,掏空后,最好不要使用strv.push_back(std::move(str));std::cout << "After move, str is "" << str << ""n";std::cout << "The contents of the vector are "" << v[0]<< "", "" << v[1] << ""n"; }

輸出:

After copy, str is "Hello" After move, str is "" The contents of the vector are "Hello", "Hello"

std::move 的函數原型定義

template <typename T> typename remove_reference<T>::type&& move(T&& t) {return static_cast<typename remove_reference<T>::type&&>(t); }

原文鏈接:c++ 之 std::move 原理實現與用法總結

總結

以上是生活随笔為你收集整理的c++ vector拷贝构造_vector------stl学习笔记一的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。