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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

C++ Primer 5th笔记(chap 13 拷贝控制)移动构造和移动赋值

發布時間:2025/3/21 c/c++ 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ Primer 5th笔记(chap 13 拷贝控制)移动构造和移动赋值 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 移動構造函數和移動賦值運算符

一般來說,拷貝一個資源會導致一些額外的開銷。在這種拷貝并非必要的情況下,定義了移動構造函數和移動賦值運算符的類就可以避免此問題。
eg.

StrVec::StrVec(StrVec &&s) noexcept //移動操作不應該拋出任何異常elements(s.elemenrs),first_free(s.first_free),cap(s.cap) {//切斷源對象與被移動資源的聯系s.elements = s.first_free = nullptr; }StrVec & strVec::operator=(StrVec &&rhs) noexcept{if(this != &rhs){free()://釋放已有元素elements = rhs.elments;first_free = rhs.first_free;cap = rhs.cap;rhs.elements = rhs.first_free = rhs.cap = nullptr;}return *this; } StrVec v1,v2; v1 = v2;//v2是左值,使用拷貝賦值運算符 StrVec getVec(istream &); v2 = getVec(cin);//getVec(cin)是一個右值;使用移動賦值運算符

eg2.

class HasPtr{ public:HasPtr(HasPtr &&p) noexcept:ps(p.ps),i(p.i){p.ps = 0}HasPtr& operator=(HasPtr rhs){swap(*this,rhs);return *this;} };hp = hp2;//hp2 是一個左值;hp2 通過拷貝構造函數來拷貝 hp = std::move(hp2);//移動構造函數來移動hp2

1.1 異常相關

  • noexcept通知標準庫不拋出異常可以節省一些額外的操作。
  • vector 在調用 push_back 可能會要求為 vector 重新分配內存,重新分配內存的過程可能會發生異常,因此push_back一般調用拷貝構造函數。 除非 vector 知道移動構造函數不會發生異常。

1.2 移后源對象的狀態

從一個對象移動數據并不會銷毀對象,但有時希望移動操作之后源對象被銷毀。當編寫一個移動操作后,源對象的狀態為:

  • 進入一個可析構的安全狀態(對象中留下的值是個未知數)
  • 對象仍然有效(可以安全地為其賦予新值或可以安全地使用而不依賴當前的值)

2. 更新三五法則

如果一個類定義了任何一個拷貝操作,它就應該定義所有的五個操作。如前所述,某些類必須定義拷貝構造函數、拷貝賦值運算符和析構函數才能正確工作。這些類通常擁有一個資源,而拷貝成員必須拷貝此資源。

3. 刪除函數

移到操作一般不會隱式地被編譯器定義為刪除函數,除非以下情形:

  • 與拷貝構造函數不同,移動構造函數被定義為刪除函數的條件是:有類成員定義了自己的拷貝構造函數且未定義移動構造函數,或者是有類成員未定義自己的拷貝構造函數并且編譯器也不能為其合成移動構造函數。移動賦值運算符的情況類似。
  • 如果有類成員的移動構造函數或移動賦值運算符被定義為刪除的或者是不可訪問的,則類的移動構造函數或移動賦值運算符被定義為刪除的。
  • 類似拷貝構造函數,如果類的析構函數被定義為刪除的或不可訪問的,則類的移動構造函數被定義為刪除的。
  • 類似拷貝賦值運算符,如果類的成員是 const 或是引用類型,則類的移動賦值運算符被定義為刪除的。

eg.

//假定Y是一個類,他定義了自己的拷貝構造函數,但未定義自己的移動構造函數 struct hasY{hasY() = default;hasY(hasY &&) = default;Y mem;//hasY將有一個刪除的移動構造函數 };hasY hy,hy2 = std::move(hy);//錯誤,移動構造函數是刪除的

4. 移動迭代器

make_move_iterator 將一個普通迭代器轉化為一個移到迭代器。

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= uninitialized_copy(make_move_iterator(begin()),make_move_iterator(end()),newdata); /*auto 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; }

總結

以上是生活随笔為你收集整理的C++ Primer 5th笔记(chap 13 拷贝控制)移动构造和移动赋值的全部內容,希望文章能夠幫你解決所遇到的問題。

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