标签:des blog 使用 os io 2014 问题 cti
int&& rvalue_ref = 99;下面就是一个右值引用例子:
#include<iostream> void f(int& i) { std::cout<<"lvalue ref: "<<i<<std::endl; } void f(int&& i) { std::cout<<"rvalue ref: "<<i<<std::endl; } int main() { int i=99; f(i); //lvalue ref called f(99); //rvalue ref called f(std::move(i)); //rvalue ref called return 0; }运行结果为:
#include<iostream> int getValue() { int i = 22; return i; } int main() { std::cout<<getValue()<<std::endl; return 0; }getValue()就是一个右值。注意:返回的这个值并不是i的引用,而是一个临时值。
const int& val = getValue(); // OK int& val = getValue(); // Wrong!但是,C++11中的右值引用允许我们绑定一个mutable引用到rvalue,但不是lvalue。换言之,右值引用可以完美的判断一个值是否为临时对象。
const int&& val = getValue(); // OK int&& val = getValue(); // OK下面进行一下比较:
void printReference (const int& value) { std::cout << value; } void printReference (int&& value) { std::cout << value; }第一个函数的参数类型为const lvalue, 它可以接收任何传入参数,无论是rvalue还是lvalue. 但是,第二个函数只能接收右值引用。
#include<iostream> void printRef(int& value) { std::cout<<"lvalue: value = "<<value<<std::endl; } void printRef(int&& value) { std::cout<<"rvalue: value = "<<value<<std::endl; } int getVal() { int tmp = 88; return tmp; } int main(){ int i = 11; printRef(i); printRef(getVal()); //printRef(88); return 0; }运行结果为:
#include<iostream> #include<algorithm> #include<vector> class Dummy { public: explicit Dummy(size_t length):_length(length), _data(new int[length]) { std::cout<<"Dummy(size_t).length = "<<_length<<"."<<std::endl; } ~Dummy() { std::cout<<"~Dummy().length = "<<_length<<"."<<std::endl; if(_data!=NULL){ std::cout<<"delete resource."<<std::endl; delete _data; } } Dummy(const Dummy&other):_length(other._length),_data(new int[other._length]) { std::cout<<"Dummy(const &Dummy).length = "<<other._length<<".Copying resource."<<std::endl; std::copy(other._data, other._data+_length, _data); } //Copy assignment operator Dummy& operator=(const Dummy& other) { std::cout<<"operator=(const Dummy&).length = "<<other._length<<". Copying resource."<<std::endl; if(this != &other) { delete _data; _length = other._length; _data = new int[_length]; std::copy(other._data, other._data+_length, _data); } return *this; } //Move constructor Dummy(Dummy&& other):_length(0),_data(NULL) { std::cout<<"Dummy(Dummy&&).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 = NULL; other._length = 0; } //Move assigment operator Dummy& operator=(Dummy&& other) { std::cout<<"operator=(Dummy&&).length = "<<other._length<<"."<<std::endl; if(this != &other) { 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 = NULL; other._length = 0; } return *this; } private: size_t _length; int* _data; }; int main() { std::vector<Dummy> vec; vec.push_back(Dummy(55)); vec.push_back(Dummy(77)); //insert a new element into the second position of the vector vec.insert(vec.begin()+1, Dummy(66)); return 0; }运行结果为:
Dummy(Dummy&& other) noexcept // C++11 - specify non-exception throwing function { _date = other._data; // shallow copy other._date = nullptr; }注意:上面函数没有分配任何新的资源,只是将内容移动了而不是拷贝: other中的内容移到了一个新成员里边,然后other中的内容被清除了。它占用了other的资源并且将other设置为了默认构造函数时的状态。最重要的事实是没有内容的分配开销。我们只是分配了一个地址,只需很少的几个机器指令即可实现。
Dummy& operator=(Dummy&& other) noexcept { _data = other._data; other._data = nullptr; return *this; }移动赋值运算符与拷贝构造函数类似,除了转移source object之前,它会释放object所拥有的资源。步骤如下:
std::vector<A> vec; vec.push_back(A(55)); vec.push_back(A(77));这两个push_back,实际上都使用的push_back(T&&), 因为传入的参数是右值。push_back(T&&)会将参数中的资源,移动到vector中的对象A, 使用的是A的移动构造函数。在C++03中,相同的这段代码会进行参数的赋值,因为会调用参数的拷贝构造函数。
std::vector<A> vec; A obj(25); // lvalue vec.push_back(obj); // push_back(const T&)不过,我们可以使用static_cast将左值引用转换为右值引用,使得调用的是push_back(T&&)。
// calls push_back(T&&) vec.push_back(static_cast<A&&>(obj));另外一种办法是,使用std::move()来实现:
// calls push_back(T&&) vec.push_back(std::move(obj));总结起来,push_back(T&&)看似总是最近选择,因为它减少了不必要的拷贝开销。然而,需要记住的是push_back(T&&)总会清空传入的参数。如果需要在执行一个push_back()操作后,仍然保持参数原始状态,则还是需要选择拷贝语义(拷贝构造函数),而不是移动语义。
#include<iostream> class Dummy { public: //constructor explicit Dummy(size_t length):_length(length),_data(new int[length]) { } //move constructor Dummy(Dummy&& other) { _data = other._data; _length = other._length; other._data = nullptr; other._length = 0; } //move assignment operator Dummy& operator= (Dummy&& other) noexcept { _data = other._data; _length = other._length; other._data = nullptr; other._length = 0; return *this; } void swap(Dummy& other) { Dummy tmp = std::move(other); other = std::move(*this); *this = std::move(tmp); } int getLength() { return _length; } int* getData() { return _data; } private: size_t _length; int* _data; }; int main() { Dummy a(11),b(22); std::cout<<a.getLength()<<" "<<b.getLength()<<std::endl; std::cout<<a.getData()<<" "<<b.getData()<<std::endl; a.swap(b); std::cout<<a.getLength()<<" "<<b.getLength()<<std::endl; std::cout<<a.getData()<<" "<<b.getData()<<std::endl; return 0; }运行结果为:
C++11线程指南(四)--右值引用与移动语义,布布扣,bubuko.com
标签:des blog 使用 os io 2014 问题 cti
原文地址:http://blog.csdn.net/shltsh/article/details/38406729