std:move基本用法和理解
場(chǎng)景:
參考:
1. Move Constructors and Move Assignment Operators (C++)
2. std::move
說明:
std::move 的函數(shù)原型.
/*** @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); }結(jié)構(gòu)體 remove_reference 的原型,就是重載了多個(gè)結(jié)構(gòu)體模板來獲取原類型 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; };例子
以下用兩個(gè)例子來說明std::move的用法.
例子1
– 原lvalue值被moved from之后值被轉(zhuǎn)移,所以為空字符串.
– 摘錄自cppreference
輸出:
After copy, str is "Hello" After move, str is "" The contents of the vector are "Hello", "Hello"例子2
– 自定義自己的類對(duì)象支持moved from 操作,需要實(shí)現(xiàn) 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. 注意,第一個(gè)函數(shù)每個(gè)對(duì)象多調(diào)用了拷貝構(gòu)造函數(shù),多創(chuàng)建了一次,而使用了move操作的只是移動(dòng)了資源
2. 注意,vector即使 push_back 第二個(gè)對(duì)象時(shí),會(huì)移動(dòng)第一個(gè)對(duì)象,很奇怪,如果你把注釋去掉的話,會(huì)發(fā)現(xiàn)資源 Moving 很多次,這是 vector 實(shí)現(xiàn)影響了,比較清楚的看出來 Move 的特性的就是 push_back 一個(gè)參數(shù).
3. 注意,g++ 4.8.1 的 vector push_back 多個(gè)對(duì)象時(shí)優(yōu)化的沒 vs 好,vs 是調(diào)用 Move 構(gòu)造器,而 g++ 是調(diào)用 Copy 構(gòu)造器,你會(huì)發(fā)現(xiàn)拷貝構(gòu)造函數(shù)會(huì)調(diào)用很多次.
總結(jié)
以上是生活随笔為你收集整理的std:move基本用法和理解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: XML具有哪些特点?相对于HTML的优势
- 下一篇: 程序媛计划——python正则表达式