当不使用带有r值的std::forward时
When not to use std::forward with r-values?
不需要std::forward
的情况有哪些?它用于包装被模板化为右值的内部函数参数(也就是说,它可以是左值或命名为右值)。类似于:
template<class T>
void outer(T&& t) {
inner(std::forward<T>(t));
}
我猜有一种情况是内部函数参数通过值传递。还有其他情况吗?当我写std::begin(std::forward<Ct>(ct))
时,我遇到了这个问题,其中Ct是模板化的。
编辑关于可能重复的
如果我没记错的话,这是一些不理解这个问题的新手第三次尝试将这个4年前的问题作为重复来结束。
"使用forward的优点?"answers"何时不使用带有r-值的std::forward?"是截然不同的问题。首先介绍了初学者的r值,其次讨论了高级C++用户的完美转发。我是元模板库和lambda库的作者,他们不需要详细的基础描述。答案中的信息和其他问题大不相同。
当模板参数类型包含值类别时,完美的转发是可能的。(如果这句话没有意义,花一分钟时间熟悉一下手头的问题。)
给定:
template <typename T>
void foo(T&& x);
在foo
体内,T
将采取U
或U&
的形式。前者意味着我们被传递了一个右值,后者意味着我们得到了一个左值。我们可以转发这样的事实:
template <typename T>
void foo(T&& x)
{
bar(std::forward<T>(x));
}
将左值传递给foo
,bar
将获得相同的左值。将右值传递给foo
,bar
获得右值。
如果不能区分一个值类别,那么转发就没有用。只有当您有一个以与上面相同的方式推导的模板参数时,它才有用。所以是的,它在这里没有用:
template <typename T>
void foo(const T& x)
{
// if this was called as foo(1), we're none the wiser
}
我正在回答我自己的问题,因为到目前为止我还没有得到满意的答案。如果我能得到哪怕是一点小小的改进/补充,我会选择你的答案作为接受。
一般来说,如果能达到完美转发的效果,std::forward
将有利于内部功能。否则就是多余的。
仅当以下任何一项为真时,才使用std::forward
包装内部函数arg:
- 内部函数参数是模板化的rvalue-ref(现在称为"转发引用")
- 内部函数具有多个重载,这些重载根据参数r/l值进行区分
- 内部函数具有多个重载,这些重载基于常量来区分左值参数
使用std::forward(对模板化函数的形式参数,其类型为T&&,T是模板的类型参数):
- 当内部函数调用是外部函数中参数的最后一次使用时,以及
- 在可能的情况下,内部函数的重载可能会也可能不会将参数作为右值引用
其原理是,当一个对象可能被右值引用作为参数传递时(这是您使用std::forward所允许的),它的信息内容可能会被破坏。所以,只有当你确信自己不再使用这些信息内容时,你才想这样做。
示例:
#include <utility>
template <class T> void f(T &&t);
template <class T> void g(const T &t);
template <class T>
void outer(bool f_first, T &&t)
{
if (f_first)
{
f(t);
g(t);
}
else
{
g(t);
f(std::forward<T>(t));
}
}
#include <string>
void foo(std::string s)
{
outer(true, s);
outer(true, s + "x");
outer(false, s);
outer(false, std::move(s));
}
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- std::向量与传递值的动态数组
- 使用一个考虑到std::map中键值的滚动或换行的键
- 为std::string的某个索引赋值
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?
- 标准::unordered_map 中的 std::array 的值初始化
- std::find,返回所有找到的值的替代方法,而不仅仅是存在重复的向量的第一个值
- 如何打印大于"无符号长长"的"std::bitset"的十进制值?
- 修改在 std::future 的 lambda 中引用捕获的值
- 如何将带有十六进制值的 std::string 转换为 std::vector<无符号字符>
- 附加使用 Struct 作为"multikey"并将 std::vector 用作映射值的映射
- 用 C++20 的给定键读取/写入 std::multimap 的所有值?
- 按索引设置 std::variant 的值
- 创建可以遍历 std::map 值的通用模板迭代器的最简单方法是什么?
- 创建 std::函数,它返回具有函数成员值的变量.分段错误
- 条件跳转或移动取决于 std::wistringstream 的未初始化值
- 为什么std::atomic的默认构造函数不默认初始化底层存储值
- 静态std::unordereded_map的默认值
- GCC9是否允许避免std::变量的无值状态
- std::stack的奇怪行为,pop()返回相同的值