当前位置: 首页 > news >正文

甘肃白银住房建设局网站5网站建站

甘肃白银住房建设局网站,5网站建站,建设工程合同签订的原则,做女装的网站C 左值和右值 左值、右值左值引用、右值引用std::move()std::move()的实现引用折叠 完美转发forward()的实现函数返回值是左值还是右值如何判断一个值是左值还是右值 左值、右值 在C11中所有的值必属于左值、右值两者之一#xff0c;右值又可以细分为纯右值、将亡值。在C11中… C 左值和右值 左值、右值左值引用、右值引用std::move()std::move()的实现引用折叠 完美转发forward()的实现函数返回值是左值还是右值如何判断一个值是左值还是右值 左值、右值 在C11中所有的值必属于左值、右值两者之一右值又可以细分为纯右值、将亡值。在C11中可以取地址的、有名字的就是左值反之不能取地址的、没有名字的就是右值将亡值或纯右值。举个例子int a bc, a 就是左值其有变量名为a通过a可以获取该变量的地址表达式bc、函数int func()的返回值是右值在其被赋值给某一变量前我们不能通过变量名找到它(bc)这样的操作则不会通过编译。 在理解C11的右值前先看看C98中右值的概念C98中右值是纯右值纯右值指的是临时变量值、不跟对象关联的字面量值。临时变量指的是非引用返回的函数返回值、表达式等例如函数int func()的返回值表达式ab不跟对象关联的字面量值例如true2”C”等。 C11对C98中的右值进行了扩充。在C11中右值又分为纯右值prvaluePure Rvalue和将亡值xvalueeXpiring Value。其中纯右值的概念等同于我们在C98标准中右值的概念指的是临时变量和不跟对象关联的字面量值将亡值则是C11新增的跟右值引用相关的表达式这样表达式通常是将要被移动的对象移为他用比如返回右值引用T的函数返回值、std::move的返回值或者转换为T的类型转换函数的返回值。 将亡值可以理解为通过“盗取”其他变量内存空间的方式获取到的值。在确保其他变量不再被使用、或即将被销毁时通过“盗取”的方式可以避免内存空间的释放和分配能够延长变量值的生命期。 左值引用、右值引用 左值引用就是对一个左值进行引用的类型。右值引用就是对一个右值进行引用的类型事实上由于右值通常不具有名字我们也只能通过引用的方式找到它的存在。 右值引用和左值引用都是属于引用类型并且都是左值。无论是声明一个左值引用还是右值引用都必须立即进行初始化。而其原因可以理解为是引用类型本身自己并不拥有所绑定对象的内存只是该对象的一个别名。左值引用是具名变量值的别名而右值引用则是不具名匿名变量的别名。 左值引用通常也不能绑定到右值但常量左值引用是个“万能”的引用类型。它可以接受非常量左值、常量左值、右值对其进行初始化。不过常量左值所引用的右值在它的“余生”中只能是只读的。相对地非常量左值只能接受非常量左值对其进行初始化。 int a 2; # 左值引用绑定到右值编译失败int b 2; # 非常量左值 const int c b; # 常量左值引用绑定到非常量左值编译通过 const int d 2; # 常量左值 const int e c; # 常量左值引用绑定到常量左值编译通过 const int b 2; # 常量左值引用绑定到右值编程通过右值值引用通常不能绑定到任何的左值要想绑定一个左值到右值引用通常需要std::move()将左值强制转换为右值例如 int a; int r1 c; # 编译失败 int r2 std::move(a); # 编译通过下表列出了在C11中各种引用类型可以引用的值的类型。值得注意的是只要能够绑定右值的引用类型都能够延长右值的生命期。 std::move() move作用是可以将一个左值转换成右值引用从而可以调用C11的拷贝构造函数。 std::move()的实现 std::move的实现主要依赖于static_castT 但同时也会做一些参数推导traits的工作。其实现如下 templatetypename T typename remove_referenceT::type move(T t) {return static_casttypename remove_referenceT::type (t); }对于t为右值的情况有如下代码 std::move(string(dengwen));首先模板类型推导确定T的类型为string得remove_reference::type为string故返回值和static的模板参数类型都为string 而move的参数就是string ,于是不需要进行类型转换直接返回。 对于t为左值的情况引入一条规则当将一个左值传递给一个参数是右值引用的函数且此右值引用指向模板类型参数(T)时编译器推断模板参数类型为实参的左值引用。有如下代码 string str(dengwen); std::move(str);此时明显str是一个左值首先模板类型推导确定T的类型为string 得remove_reference::type为string。故返回值和static的模板参数类型都为string 而move的参数类型为string 折叠后为sting 。 所以结果就为将string 通过static_cast转为string 。返回string 。 引用折叠 所有右值引用折叠到右值引用上仍然是一个右值引用。A 变成 A所有的其他引用类型之间的折叠都将变成左值引用。 A 变成 A; A 变成 A; A 变成 A 完美转发 考虑下面例子 template typename T void func(T t) {cout in func endl; }template typename T void relay(T t) {cout in relay endl;func(t); }int main() {relay(Test()); }在这个例子当中我们的期待是我们在main当中调用relayTest的临时对象作为一个右值传入relay在relay当中又被转发给了func那这时候转发给func的参数t也应当是一个右值。也就是说我们希望当relay的参数是右值的时候func的参数也是右值当relay的参数是左值的时候func的参数也是左值。 那么现在我们来运行一下这个程序我们会看到结果与我们预想的似乎并不相同 default constructor in relay copy constructor in func destructor destructor我们看到在relay当中转发的时候调用了复制构造函数也就是说编译器认为这个参数t并不是一个右值而是左值因为它有一个名字。那么如果我们想要实现我们所说的如果传进来的参数是一个左值则将它作为左值转发给下一个函数如果它是右值则将其作为右值转发给下一个函数我们应该怎么做呢 这时我们需要std::forwardT()。与std::move()相区别的是move()会无条件的将一个参数转换成右值而forward()则会保留参数的左右值类型。所以我们的代码应该是这样 template typename T void func(T t) {cout in func endl; }template typename T void relay(T t) {cout in relay endl;func(std::forwardT(t)); }int main() {relay(Test()); }现在运行的结果就成为了 default constructor in relay move constructor in func destructor destructor而如果我们的调用方法变成 int main() {Test t;relay(t); }那么输出就会变成 default constructor in relay copy constructor in func destructor destructor完美地实现了我们所要的转发效果。 forward()的实现 std::forward()提供两个重载版本 一个针对左值 一个针对右值。 templatetypename _Tp constexpr _Tp forward(typename std::remove_reference_Tp::type __t) noexcept { return static_cast_Tp(__t); }templatetypename _Tp constexpr _Tp forward(typename std::remove_reference_Tp::type __t) noexcept { static_assert(!std::is_lvalue_reference_Tp::value, template argumentsubstituting _Tp is an lvalue reference type); return static_cast_Tp(__t); }根据以下实例进行分析 templatetypename T void foo(T fparam) { std::forwardT(fparam); }int i 7; foo(i); foo(47);在foo(i) 如果传入的是一个左值 那么foo中T的类型将是int, fparam类型是int , 经过折叠为int. 因此在std::forward模板函数中推断出T的类型为int,因此std::remove_reference用int 进行实例化。std::remove_reference的type成员是int。forward返回类型为int , 折叠为int。forward的参数类型__t为int。static_castint 折叠为static_castint 。 因此std::forward最终被实例化如下 int forward(int __t){ return static_castint (__t) }可以发现函数什么都不用做 最终的传入forward的左值引用被保留了。 在foo(47)中 传入的是一个右值那么foo中T的类型将是int, fparam类型是T, 因此在std::forward模板函数中推断出T的类型为int。因此 std::remove_reference用int 进行实例化。std::remove_reference的type成员是int。forward返回类型为int。forward的参数类型__t为int。static_castint 折叠为static_castint 因此std::forward最终被实例化如下 int forward(int __t){ return static_castint (__t) }可以发现函数什么都不用做 最终的传入forward的右值引用被保留了。 通过以上分析 实际上无论传递左值还是右值 forward都可以完美转发 并且函数内部什么都不用做。 函数返回值是左值还是右值 如果函数返回值是引用类型则为左值。如果函数返回值是值类型则为右值。 如何判断一个值是左值还是右值 右值是能够赋值给左值但是左值不能赋值给右值。
http://www.pierceye.com/news/218102/

相关文章:

  • 四大商业网站镇江制作网站的
  • 做网站系统学校宠物交易网站模板
  • 佛山市官网网站建设哪家好瑶海合肥网站建设
  • 微网站app建筑图片大全高清
  • 贵阳金阳网站建设公司网站开发与维护书
  • 做非法网站判什么邢免抵退税在哪个网站做
  • 手机网站如何制作免费网站的内容和功能
  • 宁波网站推广合作商品牌设计包括
  • 辽宁省建设厅官方网站制作一个静态网站的步骤
  • 营销外贸网站建设北京房地产网站建设
  • 青海网站建设公司代理记账如何获取客户
  • 做视频必须知道的一些网站企业搜索
  • 网站定制开发北京淮南网新闻最新消息
  • 网站描述怎么写比较好企业信息系统案例
  • 青峰集团响应式网站功能性的网站归档系统
  • 龙岩招聘求职网站有哪些网站建设促销活动
  • 人力资源服务外包网站tdk优化文档
  • 做黑网站吗江苏建筑业网
  • 地区门户网站 wap appcdn接入wordpress出错
  • 网站建设为什么学flash最新新闻消息事件
  • 高端网站建设需要的人员配备编辑目录中的字体 wordpress
  • 电脑维修网站模板金融商城快捷申请网站模板下载
  • wordpress 本地建站教程化纤公司网站建设
  • 广州网站设计公司新闻给客户做非法网站
  • 微商城手机网站制作公司痞子 wordpress
  • 公司网站备案申请鹤山做网站
  • 南阳那里有做网站的聊城网站优化
  • 网站开发技术实验教程长沙网站托管公司排名
  • 美妆网站建设项目计划书软件开发培训班机构
  • 小视频网站怎么做seo网络优化师