无忧创业网,痴汉十人队中文版,9c8977
c++11 中的 move() 是这样一个函数,它接受一个参数,然后返回一个该参数对应的右值引用.
就这么简单!你甚至可以暂时想像它的原型是这样的(当然是错的)
t&& move(t& val);
holder(holder& other)
holder(holder&& other)
上面是2个重载函数
holder& operator=(holder& other)
holder& operator=(holder&& other)
上面是2个重载函数
具体看下面的例子:假设我们有一个类,它包含了一些资源。我们的愿望是:当调用拷贝构造函数或者赋值语句时,我们不想再new一个resource的对象,因为要new一个resource对象,即浪费空间,有浪费时间。
解决办法:利用右值引用。
holder h2(std::move(get_holer()))
h1 = get_holer()
完整代码:
#include <iostream> using namespace std; class resource{}; class holder{ public: //构造函数 holder(){res = new resource();} //析构函数 ~holder(){ //res不为null,就释放res if (res)delete res; } //拷贝构造函数 holder(const holder& other){ cout << "holder&" << endl; res = new resource(*other.res); } holder(holder& other){ cout << "holder&1" << endl; res = new resource(*other.res); } //右值 holder(holder&& other){ cout << "holder&&" << endl; res = other.res; other.res = nullptr; } //赋值 holder& operator=(const holder& other){ cout << "operator" << endl; delete res; res = new resource(*other.res); return *this; } holder& operator=(holder& other){ cout << "operator1" << endl; delete res; res = new resource(*other.res); return *this; } //右值 holder& operator=(holder&& other){ cout << "operator &&" << endl; std::swap(res, other.res); return *this; } private: resource* res; }; holder get_holer(){ holder h; return h; } int main(void){ holder h1,h11; holder h2(std::move(get_holer()));//调用holder(holder&& other) holder h3(get_holer());//编译器自动优化了,没有调用拷贝构造函数 holder h4(h11); h1 = h2;//调用operator(holder&); h1 = get_holer();//调用operator(holder&&); }
上面的例子有个需要注意的地方,就是下面这行代码
holder h3(get_holer());//编译器自动优化了,没有调用拷贝构造函数
这行代码乍一看,应该调用拷贝构造函数。但是实际用gdb,断点调试时,发现并没有调用拷贝构造函数。
65 holder h2(std::move(get_holer())); (gdb) n holder&& 66 holder h3(get_holer());//编译器自动优化了,没有调用拷贝构造函数 (gdb) s get_holer () at rvalue_move.cpp:59 59 holder h;//调用一次构造函数,在下面的9行可以看到 (gdb) s holder::holder (this=0x7fffffffe180) at rvalue_move.cpp:9 9 holder(){res = new resource();} //调用构造函数,创建h对象 (gdb) s get_holer () at rvalue_move.cpp:60 60 return h; //返回h对象 (gdb) p h //查看h对象里面res的内存地址 $12 = {res = 0x603070} (gdb) p &h //查看h的内存地址 $13 = (holder *) 0x7fffffffe180 (gdb) n 61 } (gdb) n main () at rvalue_move.cpp:67 (gdb) p h3 //查看h3对象里面res的内存地址,发现h3的res的内存地址和在函数get_holer()里创建的h对象的res的内存地址相同 $14 = {res = 0x603070} (gdb) p &h3 //查看h3的内存地址后,发现h3的内存地址和在函数get_holer()里创建的h对象的内存地址相同 $15 = (holder *) 0x7fffffffe180
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
如何在没有core文件的情况下用dmesg+addr2line定位段错误
用QT制作3D点云显示器——QtDataVisualization
网友评论