gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 18:31:11 27 4
gpt4 key购买 nike

std::movestd::forward 之间的区别是众所周知的,我们使用后者来保存转发对象的值类别,而前者用于转换为右值引用以启用移动语义。

effective modern 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,它的计算结果为左值引用。

关于c++ - 为什么不总是使用 std::forward?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36228791/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com