深入理解(实例) -- c++ 右值引用 左值引用
来源:互联网 发布:淘宝 店招 css 编辑:程序博客网 时间:2024/06/16 08:35
c++ 右值引用 左值引用
下面代码 看出右值引用 跟左值引用的相似之处,都具有别名的左右,可以与它引用的变量共同修改地址内的内容
左值/右值引用可以延长临时变量的寿命,直到该右值引用的寿命结束才析构
右值引用可以直接引用临时变量(如常量 1 ,3.1等),且可以对它进行修改(不指定const)
左值引用一般不会用于引用临时变量,虽然通过一些手段可以编译成功,但不安全也没有意义
struct RefTest{ RefTest() { str = "constructor"; } ~RefTest() { str = "destructor"; std::cout<<str.c_str()<<" ~RefTest"<<std::endl; } std::string&& getrvalue_ref() && { return std::move(str); } std::string& getlvalue_ref() { return (str); } std::string str;};void test1(){ RefTest a; RefTest&& b = std::move(a); std::cout<<a.str.c_str()<<"\t"<<b.str.c_str()<<std::endl; a.str = "change"; std::cout<<a.str.c_str()<<"\t"<<b.str.c_str()<<std::endl;//constructor constructor// change change// int& c = 3; //不能编译通过,右边是右值 int&& c = 3; c++; std::cout<<c<<"\t"<<std::endl;//4 RefTest(); //立即析构// destructor ~RefTest RefTest&& d = RefTest(); //函数结束后析构 d.str = "change"; std::cout<<d.str.c_str()<<std::endl;// change std::string&& e = RefTest().getrvalue_ref(); std::cout<<e.c_str()<<"\t"<<std::endl; e = "change"; std::cout<<e.c_str()<<"\t"<<std::endl;// destructor ~RefTest// destructor// change std::string& f = RefTest().getlvalue_ref(); std::cout<<f.c_str()<<"\t"<<std::endl; f = "change"; std::cout<<f.c_str()<<"\t"<<std::endl;// destructor ~RefTest// destructor// change// destructor ~RefTest// destructor ~RefTest}
对于函数的返回值如果是临时变量(函数内建的变量,既不是参数变量也不是类成员变量),不能返回引用!
对c++ 在编译的时候会对返回值进行优化,如果返回的是临时变量(注意不是引用!),则会直接使用该临时变量的地址,不会进行内容的迁移和内参的释放,因此效率比较高。这也说明返回值处一般不需要使用move来强制转换右值,多此一举。
int getrvalue(){ return 2;}int& getlvalue_ref(){ int a = 3; return a;}struct Rvaluetest{ Rvaluetest(int i):str(new char[15]) { value = i; str[0] = 'c'; str[1] = 0; cstr = "test"; } ~Rvaluetest() { value = 0; std::cout<<" ~Rvaluetest "<<cstr.c_str()<<std::endl; delete str; } int value = 2; char * const str; std::string cstr;};Rvaluetest&& getrvalue_ref(){ Rvaluetest a(5); return std::move(a);}Rvaluetest getrvalue_test(){ Rvaluetest a(5); return (a);}void RefTest(){// int& c = getrvalue(); //error invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’ const int& c = getrvalue(); std::cout<<c<<"\t"<<std::endl;// 2 int&& d = getrvalue(); d++; std::cout<<d<<"\t"<<std::endl;// 3 int& e = getlvalue_ref(); //编译能通过 但 再次调用该变量会出现 Segmentation fault// std::cout<<e<<"\t"<<std::endl; //Segmentation fault Rvaluetest&& f = getrvalue_ref(); std::cout<<++f.value<<"\t"<<f.str<<" "<<f.cstr.c_str()<<std::endl; //乱码,说明运行了析构函数,因此虽然能够编译通,并能够运行,但是不安全 //右值引用终究还是引用,他并没有对内存的释放权,如果它引用的内存寿命短暂,可能会出错// ~Rvaluetest test// 1 �$��� Rvaluetest g = getrvalue_test(); //因为c++ 编译器的优化,该函数内建的临时变量并没有运行析构函数,而是整体通过返回值返回转移到g,寿命延长 //函数的返回值是右值,这也说明,c++中右值的赋值是直接地址赋值,并没有内容的迁移和内参释放,高效 std::cout<<++g.value<<"\t"<<g.str<<" "<<g.cstr.c_str()<<std::endl;// 6 c test// ~Rvaluetest test}
阅读全文
0 0
- 深入理解(实例) -- c++ 右值引用 左值引用
- C++引用(左值引用,右值引用)
- C++——左值引用和右值引用
- C++——左值引用和右值引用
- 左值、右值、左值引用、右值引用
- 左值、右值、左值引用、右值引用
- 左值 右值 左值引用 右值引用
- 引用,左值,右值
- 左值引用与右值引用
- 左值引用与右值引用
- 左值引用与右值引用
- 左值引用与右值引用
- 左值引用和右值引用
- 引用左值和引用右值
- 左值引用和右值引用
- 左值引用(&)和右值引用(&&)
- C++/C++11中左值、左值引用、右值、右值引用的使用
- C++拾遗--引用(左值引用、右值引用)
- 计数
- 小笺何解
- 独木舟上的旅行
- 20171119
- 2.消息中间件概述
- 深入理解(实例) -- c++ 右值引用 左值引用
- golang标准库的分析os包(https://segmentfault.com/a/1190000000376807)
- J2SE -Java数据类型
- Docker容器安装-多节点PbsPro
- 小程序如何给view层追加数据
- iOS今日头条选择框、动画效果、FlappyBird游戏源码
- CSDN的积分越来越贵了
- MatlabR2012a显示使用过期的注册文件破解
- +-字符串