[英]Why not always use std::forward?
std::move
和std::forward
之間的區別是眾所周知的,我們使用后者保留轉發對象的值類別,並使用前者轉換為rvalue引用以啟用移動語義。
在有效的現代C ++中 ,存在一種指導原則
在rvalue引用上使用
std::move
,在通用引用上使用std::move
std::forward
。
但在以下場景中( 以及我們不想更改值類別的場景 ),
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
,它計算為左值引用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.