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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

std:move基本用法和理解

發布時間:2025/3/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 std:move基本用法和理解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

場景:

  • C++ 標準庫使用比如vector::push_back 等這類函數時,會對參數的對象進行復制,連數據也會復制.這就會造成對象內存的額外創建, 本來原意是想把參數push_back進去就行了.
  • C++11 提供了std::move 函數來把左值轉換為xrvalue, 而且新版的push_back也支持&&參數的重載版本,這時候就可以高效率的使用內存了.
  • 對指針類型的標準庫對象并不需要這么做.
  • 參考:

    1. Move Constructors and Move Assignment Operators (C++)
    2. std::move

    說明:

  • std::move(t) 用來表明對象t 是可以moved from的,它允許高效的從t資源轉換到lvalue上.
  • 注意,標準庫對象支持moved from的左值在moved 之后它的對象原值是有效的(可以正常析構),但是是unspecified的,可以理解為空數據,但是這個對象的其他方法返回值不一定是0,比如size().所以,moved from 之后的對象最好還是不要使用吧?(如有不正確理解,請告知)
  • 對本身進行move,并賦值給本身是undefined的行為.
  • std::vector<int> v = {2, 3, 3}; v = std::move(v); // undefined behavior

    std::move 的函數原型.

    /*** @brief Convert a value to an rvalue.* @param __t A thing of arbitrary type.* @return The parameter cast to an rvalue-reference to allow moving it. */ template<typename _Tp>constexpr typename std::remove_reference<_Tp>::type&&move(_Tp&& __t) noexcept{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }

    結構體 remove_reference 的原型,就是重載了多個結構體模板來獲取原類型 type.

    /// remove_reference template<typename _Tp>struct remove_reference{ typedef _Tp type; };template<typename _Tp>struct remove_reference<_Tp&>{ typedef _Tp type; };template<typename _Tp>struct remove_reference<_Tp&&>{ typedef _Tp type; };

    例子

    以下用兩個例子來說明std::move的用法.

    例子1

    – 原lvalue值被moved from之后值被轉移,所以為空字符串.
    – 摘錄自cppreference

    void TestSTLObject() {std::string str = "Hello";std::vector<std::string> v;// uses the push_back(const T&) overload, which means// we'll incur the cost of copying strv.push_back(str);std::cout << "After copy, str is \"" << str << "\"\n";// uses the rvalue reference push_back(T&&) overload,// which means no strings will be copied; instead, the contents// of str will be moved into the vector. This is less// expensive, but also means str might now be empty.v.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"

    例子2

    – 自定義自己的類對象支持moved from 操作,需要實現 Move Constructors and Move Assignment Operators

    #include <iostream> #include <stdio.h>#include <utility> #include <vector> #include <string>class MemoryBlock { public:// Simple constructor that initializes the resource.explicit MemoryBlock(size_t length): _length(length), _data(new int[length]){std::cout << "In MemoryBlock(size_t). length = "<< _length << "." << std::endl;}// Destructor.~MemoryBlock(){std::cout << "In ~MemoryBlock(). length = "<< _length << ".";if (_data != nullptr){std::cout << " Deleting resource.";// Delete the resource.delete[] _data;}std::cout << std::endl;}// Copy constructor.MemoryBlock(const MemoryBlock& other): _length(other._length), _data(new int[other._length]){std::cout << "In MemoryBlock(const MemoryBlock&). length = "<< other._length << ". Copying resource." << std::endl;std::copy(other._data, other._data + _length, _data);}// Copy assignment operator.MemoryBlock& operator=(const MemoryBlock& other){std::cout << "In operator=(const MemoryBlock&). length = "<< other._length << ". Copying resource." << std::endl;if (this != &other){// Free the existing resource.delete[] _data;_length = other._length;_data = new int[_length];std::copy(other._data, other._data + _length, _data);}return *this;}// Retrieves the length of the data resource.size_t Length() const{return _length;}// Move constructor.MemoryBlock(MemoryBlock&& other): _data(nullptr), _length(0){std::cout << "In MemoryBlock(MemoryBlock&&). length = "<< other._length << ". Moving resource." << std::endl;// Copy the data pointer and its length from the// source object._data = other._data;_length = other._length;// Release the data pointer from the source object so that// the destructor does not free the memory multiple times.other._data = nullptr;other._length = 0;}// Move assignment operator.MemoryBlock& operator=(MemoryBlock&& other){std::cout << "In operator=(MemoryBlock&&). length = "<< other._length << "." << std::endl;if (this != &other){// Free the existing resource.delete[] _data;// Copy the data pointer and its length from the// source object._data = other._data;_length = other._length;// Release the data pointer from the source object so that// the destructor does not free the memory multiple times.other._data = nullptr;other._length = 0;}return *this;}private:size_t _length; // The length of the resource.int* _data; // The resource. };void TestSTLObject() {std::string str = "Hello";std::vector<std::string> v;// uses the push_back(const T&) overload, which means// we'll incur the cost of copying strv.push_back(str);std::cout << "After copy, str is \"" << str << "\"\n";// uses the rvalue reference push_back(T&&) overload,// which means no strings will be copied; instead, the contents// of str will be moved into the vector. This is less// expensive, but also means str might now be empty.v.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";}void TestMyObjectWithoutUseMove() {std::vector<MemoryBlock> v;MemoryBlock mb1(25);// MemoryBlock mb2(75);// MemoryBlock mb3(50);v.push_back(mb1);//v.push_back(mb2);//v.insert(v.begin() + 1, mb3); }void TestMyObjectWithUseMove() {std::vector<MemoryBlock> v;MemoryBlock mb1(25);// MemoryBlock mb2(75);// MemoryBlock mb3(50);v.push_back(std::move(mb1));//v.push_back(MemoryBlock(75));//v.insert(v.begin() + 1, MemoryBlock(50)); }int main(int argc, char const *argv[]) {//TestSTLObject();TestMyObjectWithoutUseMove();std::cout << "......................................." << std::endl;TestMyObjectWithUseMove();return 0; }

    輸出:
    1. 注意,第一個函數每個對象多調用了拷貝構造函數,多創建了一次,而使用了move操作的只是移動了資源
    2. 注意,vector即使 push_back 第二個對象時,會移動第一個對象,很奇怪,如果你把注釋去掉的話,會發現資源 Moving 很多次,這是 vector 實現影響了,比較清楚的看出來 Move 的特性的就是 push_back 一個參數.
    3. 注意,g++ 4.8.1 的 vector push_back 多個對象時優化的沒 vs 好,vs 是調用 Move 構造器,而 g++ 是調用 Copy 構造器,你會發現拷貝構造函數會調用很多次.

    In MemoryBlock(size_t). length = 25. In MemoryBlock(const MemoryBlock&). length = 25. Copying resource. In ~MemoryBlock(). length = 25. Deleting resource. In ~MemoryBlock(). length = 25. Deleting resource. ....................................... In MemoryBlock(size_t). length = 25. In MemoryBlock(MemoryBlock&&). length = 25. Moving resource. In ~MemoryBlock(). length = 0. In ~MemoryBlock(). length = 25. Deleting resource.

    總結

    以上是生活随笔為你收集整理的std:move基本用法和理解的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 国产一区日韩 | 少妇性l交大片免费观看 | 伊人tv | 99国产揄拍国产精品 | 午夜寂寞福利 | 日韩插 | 又色又爽又黄gif动态图 | 久久久久亚洲av无码专区 | 久久九九国产视频 | 熟女熟妇伦久久影院毛片一区二区 | 精品在线视频一区二区 | 亚洲小说春色综合另类 | 免费观看理伦片在线播放视频软件 | 欧洲女同同性吃奶 | 亚洲一区二区三区高清在线 | 美女擦边视频 | 巨乳女教师的诱惑 | 操操操日日日 | av毛片网站 | 东京热一本视频一区 | www.av72| 国产不卡在线观看视频 | 视频一区二区在线播放 | 日韩精品高清视频 | 视屏一区 | 久久奇米 | 国产日产亚洲系列最新 | 天堂精品一区二区三区 | 国产在线1区 | 极品美妇后花庭翘臀娇吟小说 | 欧美丰满美乳xxx高潮www | 毛片资源 | 精品少妇久久 | 91精品国产入口 | 日操操| 成人午夜在线免费观看 | 伊人久久一区二区 | 51国产在线 | 一级片免费在线 | 国产成a人亚洲精v品无码 | 青娱乐超碰在线 | 亚洲伦理在线观看 | 波多野结av衣东京热无码专区 | www狠狠爱 | 超碰老司机| 97国产精品视频人人做人人爱 | 隔壁人妻偷人bd中字 | xxx色| av在线网址观看 | www.夜夜爽| 无码人妻一区二区三区在线视频 | 精品国产91乱码一区二区三区 | 人妻洗澡被强公日日澡电影 | av网址观看| 空姐吹箫视频大全 | 日韩欧美成人精品 | 俄罗斯黄色大片 | 久久久久久久av | 国产一区二区啪啪啪 | 国产美女视频一区 | 日韩精品无码一本二本三本色 | 色噜 | 国产精品毛片久久 | 天堂在线精品视频 | 国产香蕉视频在线播放 | 欧美成人免费一级人片100 | 免费a级黄色片 | 日韩最新中文字幕 | 黄大片18满岁| 国产69精品久久久久久久久久 | av黄色免费在线观看 | 亚洲国产成人一区二区精品区 | 爱射网| 亚洲日日夜夜 | 波多野一区二区三区 | 一区欧美 | 成人免费毛片足控 | 日韩精品福利视频 | 国产在线视频一区二区三区 | 四虎影库 | 国产精品扒开腿做爽爽爽男男 | 日韩国产一级 | 永久在线观看 | 日本特黄色片 | 18欧美性xxxx极品hd | 日本中文字幕一区 | 丰满熟女人妻一区二区三 | av影视在线| 成人亚洲免费 | 性久久久久久久久久久久 | 国产精品探花一区二区在线观看 | 丰满人妻一区二区三区46 | 国产视频一区二区三区四区 | 自拍偷拍色图 | 少妇熟女高潮流白浆 | 亚洲区在线播放 | 国产sm调教视频 | 96精品视频在线观看 | 日韩极品在线观看 |