move 和 forward
move
关键的话:
std::move 并不进行任何移动,std::forward 也不进行任何转发。
move 和 forward 在运行期都无所作为。不会生成任何可执行代码,连一个字节都不会生成。
函数形参永远是左值。 具名变量永远是左值。但是不具名的变量不一定是右值。(例如字符串字面量 “hello world” 也是左值)
参考:
https://zh.cppreference.com/w/cpp/language/identifiers
命名某个变量、函数、概念的特化 (C++20 起)或枚举项的标识符可以作为表达式使用。仅由这个标识符组成的表达式的结果,是该标识符所命名的实体。若该标识符命名的是某个函数、变量、模板形参对象 (C++20 起)或数据成员,则表达式的值类别为左值,否则为纯右值(例如枚举项是纯右值表达式,概念的特化是 bool 纯右值 (C++20 起))。
可以看到,一个枚举项命名的并非是某个函数、变量、模板形参对象 (C++20 起)或数据成员,因此非左值,为纯右值。
我理解中左值就是可以出现在operator=左侧,而右值是只能出现在operator=右侧。
但是对于C++自定义的类,会有一些意外。比如string()是一个临时对象但也能放在左边,不过没有意义。
值类别参考:https://zh.cppreference.com/w/cpp/language/value_category
再参考标准规格书:ISO_IEC_14882__2020-12
In general, the effect of this rule is that named rvalue references are treated as lvalues and unnamed rvalue references to objects are treated as xvalues; rvalue references to functions are treated as lvalues whether named or not.
具名右值引用是一个左值,不具名右值引用是一个亡值 (xvalue)(“将亡 (expiring)”的值)
forward
forward 不进行任何转发。只是在某个特定条件满足下执行一个强制转换(static_cast)罢了。
首先理解万能引用的模板推导规则:
template<typename T>
void f(T&& param);
万能引用只能是 T&& 的形式,即 T 不能被修饰(如 cv 修饰符,否则为右值引用形式)。
推导规则:左值 则 T 被推导为 左值引用,右值 则 T 被推导为 不带引用的情况。
例如(一个简单的测试万能引用的程序):
#include <iostream>
#include <type_traits>template<typename T>
void f(T&& param)
{std::cout << std::boolalpha;std::cout << std::is_reference_v<T> << std::endl;//std::cout << std::is_reference_v<decltype(param)> << std::endl;
}int main()
{const int a = 5;f(a); // T 为 const int& f(10);
}
推导不会丢掉 cv 修饰符 (cv (const and volatile) type qualifiers)。
boolalpha操纵符,否则 ture 会输出为 1
引用折叠:&& + && == &&
只有四种语境会发生:模板实例化、auto型别生成、创建和运用 typedef 和别名声明、decltype
个人观点:其实就是推导(deduction)语境。
简单示例:
#include <vector>std::vector<int> vec;template<typename T>
void f(T&& param)
{vec.push_back(std::forward<T>(param));
}int main()
{int b = 5;const int& a = b;f(5);f(a);
}
关于 _t 与 _v
参考:https://rules.sonarsource.com/cpp/RSPEC-6020
The “_t” and “_v” version of type traits should be used instead of “::type” and “::value”
Even if the old variant still exists, the new one, which uses _t (C++14) and _v (C++17) suffixes as discriminant, should be preferred.
template<class T>
void f(T t) {static_assert (std::is_arithmetic<T>::value); // Noncompliantusing rawType = std::remove_cv<T>::type; // Noncompliant
}
template<class T>
void f(T t) {static_assert (std::is_arithmetic_v<T>); // Compliant, C++17using rawType = std::remove_cv_t<T>; // Compliant, C++14
}
top-level const qualifier
C++Primer 5th 2.4.3 :
可见,常量指针为顶层const,指向常量的指针为底层const,const int* const 既是顶层又是底层。引用则没有顶层。
而 is_const_v
只能检查顶层const。要检查底层const,如下:
std::cout << std::boolalpha;
std::cout << std::is_const_v<const int> << std::endl;
std::cout << std::is_const_v<std::remove_pointer_t<const int*>> << std::endl;
std::cout << std::is_const_v<std::remove_reference_t<const int&>> << std::endl;
输出全为 true。
move 和 forward相关推荐
- C++ std::move/std::forward/完美转发
右值引用相关的几个函数:std::move, std::forward 和 成员的 emplace_back; 通过这些函数我们可以避免不必要的拷贝,提高程序性能. move 是将 对象的状态 或者 ...
- C++语法——右值引用、移动构造和赋值、万能引用和转发、move和forward底层实现
目录 一.右值引用 (一).何为右值 (二).右值引用 (三).右值和左值的互相传递 ①左值->右值引用 ②右值->左值引用 (四).右值引用的自身属性 二.移动构造和移动赋值 (一).移 ...
- 深入理解C++中的move和forward!
导语 | 在C++11标准之前,C++中默认的传值类型均为Copy语义,即:不论是指针类型还是值类型,都将会在进行函数调用时被完整的复制一份!对于非指针而言,开销极其巨大!因此在C++11以后,引入 ...
- c++11 中的 move 与 forward
一. move 关于 lvaue 和 rvalue,在 c++11 以前存在一个有趣的现象:T& 指向 lvalue (左传引用), const T& 既可以指向 lvalue 也可 ...
- c++11特性move和forward区别
1:move属于强转,左值变右值 2:forward左值变左值,右值变右值(不是强转)
- (原创)C++11改进我们的程序之move和完美转发
http://www.cnblogs.com/qicosmos/p/3376241.html 本次要讲的是右值引用相关的几个函数:std::move, std::forward和成员的emplace_ ...
- 一文详解点云分割算法
作者丨书生意封侯@知乎 来源丨https://zhuanlan.zhihu.com/p/470782623 编辑丨3D视觉工坊 从某种意义上说,地面点剔除(分割)也属于点云分割的一种,但两者技术路线有 ...
- 程序员的量化交易之路(35)--Lean之DataFeed数据槽3
转载需注明出处:http://blog.csdn.net/minimicall,http://cloudtrade.top/ Lean引擎的模块划分非常的规范.其中DataFeed是数据槽,就是供应数 ...
- 全部python编程语言-可以用 Python 编程语言做哪些神奇好玩的事情?
贪吃蛇.迷宫.吃豆人.扫雷.Flappy Bird...这些游戏可以是非常经典,甚至伴随着很多人的童年回忆.那么,你是否想过自己开发一款专属游戏?是否思考过开发这样一款游戏需要多少工作量? /> ...
最新文章
- 「镁客早报」阿里巴巴与Office Depot合作,服务美国小企业;HTC与印厂商谈品牌许可协议,或退出手机市场...
- commonjs是什么_第一步:面试官让我解释什么是Common.js和ES6模块化
- Java JDBC
- 牛客网——10进制 VS 2进制
- android.animation(1) - ValueAnimator的ofInt(), ofFloat(), addUpdateListener(), addListener()(转)
- lowerBound与upperBound
- perl6正则 4: before / after 代码断言: ?{} / !{}
- 内置对象和自定义对象的原型链
- 软件版本控制Subversion和Git
- wsdl2java wsdl文件_使用axis2的wsdl2java把wsdl生成java文件
- 来料加工企业使用ERP系统作用有哪些
- 二阶魔方万能还原公式_【二阶篇】一个万能公式还原二阶魔方
- web前端vue项目完整步骤。pc端
- 实现Excel单元格中的下拉选项和数据有效性
- 微信小程序可以打开公众号文章
- 闪购网站Gilt从Rails迁移到Scala
- 炼数成金数据分析课程---13、回归分析
- 数字化招聘:猎聘、快手同行不同路
- so动态库生成、链接方法
- 数图互通高校房产管理——公积金补贴管理