加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 为什么不总是使用std :: forward?

发布时间:2020-12-16 03:44:44 所属栏目:百科 来源:网络整理
导读:std :: move和std :: forward之间的区别是众所周知的,我们使用后者保留转发对象的值类别,并使用前者转换为rvalue引用以启用移动语义. 在有效的现代C中,存在一种指导原则 use std::move on rvalue references, std::forward on universal references. 但在以
std :: move和std :: forward之间的区别是众所周知的,我们使用后者保留转发对象的值类别,并使用前者转换为rvalue引用以启用移动语义.

在有效的现代C中,存在一种指导原则

use std::move on rvalue references,std::forward on universal references.

但在以下场景中(以及我们不想更改值类别的场景),

template <class T>
void f(vector<T>&& a)
{
    some_func(std::move(a)); 
}

如果a不是转发引用而是简单的右值引用,那么执行以下操作是否完全相同?

template <class T>
void f(vector<T>&& a)
{
    some_func(std::forward<decltype(a)>(a)); 
}

因为这可以很容易地封装在像这样的宏中,

#define FWD(arg) std::forward<decltype(arg)>(arg)

如此总是使用这个宏定义不方便吗?

void f(vector<T>&& a)
{
    some_func(FWD(a)); 
}

写这两种方式不完全相同吗?

解决方法

呃.值得商榷.在您的特定示例中,它是等效的.但我不会养成习惯.一个原因是因为您希望在转发和移动之间进行语义区分.另一个原因是因为要拥有一致的API,除了FWD之外你还必须拥有MOV,这看起来很糟糕而且什么都不做.但更重要的是,您的代码可能会意外失败.

请考虑以下代码:

#include <iostream>

using namespace std;

#define FWD(arg) std::forward<decltype(arg)>(arg)

struct S {
    S() { cout << "S()n"; }
    S(const S&) { cout << "S(const S&)n"; }
    S(S&&) { cout << "S(S&&)n"; }
};

void some_func(S) {}

void f(S&& s)
{
    some_func(FWD(s)); 
}

int main()
{
    f(S{});
}

打印出来

S()
S(S&&)

但是,如果我只是改变FWD线以获得另一对(看似可选的)括号,如下所示:

void f(S&& s)
{
    some_func(FWD((s))); 
}

现在我们得到了

S()
S(const S&)

这是因为现在我们在表达式上使用了decltype,它计算为左值引用.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读