"auto v = f()"和"auto&& v = f()"有什么区别?

What's the difference between "auto v = f()" and "auto&& v = f()"?

本文关键字:auto 区别 什么      更新时间:2023-10-16
#include <vector>
using namespace std;
vector<int> f()
{
    return{};
}
// Update: Below is not compilable
void g(vector<int>)
{}
// Update: Below is the my initial intent.
/*
void g(const vector<int>&)
{}
*/
void g(vector<int>&&)
{}
int main()
{
    auto       v1 = f();
    auto&& v2 = f();
    g(forward<vector<int>>(v1));
    g(forward<vector<int>>(v2));
}

C 11保证g(forward<vector<int>>(v1))会致电f(vector<int>)f(const vector<int>&),并且g(forward<vector<int>>(v2))将调用f(vector<int>&&)

区别在于 v1是向量,而 v2是对向量的rvalue引用。

超载g您的完成方式是一个非常糟糕的主意。如果该参数是CV Unqualified Rvalue,则该调用将是模棱两可的,因为两个g的C可以接受具有身份转换序列的RVALUE。但是,可以接受一个过载T&,另一个超负荷以T&&

如果要转发f()的值类别,请不要像完成v1一样复制/移动它。这会破坏价值类别信息。 v1将永远是lvalue。

此外,您无法正确使用std::forwardv1v2都将被施放为rvalue参考,在这种情况下,在超载分辨率下的行为。

这是std::forward的适当用法:

void g(vector<int>&);
void g(vector<int>&&);
int main() {
    auto&& v1 = function_returning_lvalue_vector();
    auto&& v2 = function_returning_rvalue_vector();
    g(forward<decltype(v1)>(v1));  // calls lvalue overload
    g(forward<decltype(v2)>(v2));  // calls rvalue overload
}

有一个与返回函数关联的对象,称为返回值f()的返回值是vector<int>

在C 11和C 14中,其中f()按值返回:

  • auto v1 = f();使用复制/移动构造函数初始化了 vector<int>,该 CC_23将从返回值中称为 v1。这是复制省略上下文。
  • auto&& v2 = f();将名称v2指定为返回值,并且返回值的寿命已延长。

如果编译器确实实现了复制率,则这两个代码具有相同的效果。从C 17中,带有所谓的"保证复制责任",这两个代码将相同。

由"相同",除了decltype(identifier)的结果外,我的意思是相同的。


您的两个g调用之间没有区别。在这两种情况下,该参数都是std::vector型的LVALUE。表达式 v1v2不要"记住"它们是否最初是返回值对象。

std::forward仅在给定一个模板参数时才是有用的,该模板参数是完美转发扣除的结果(因此,可能是参考类型)。

建议使用decltypedecltype(identifier)是一种特殊情况,确实回想起标识符在应用auto扣除后如何声明。

  • decltype(v1)vector<int>
  • decltype(v2)vector<int> &&

,但是现在我们有:

  • std::forward<decltype(v1)>vector<int> &&
  • std::forward<decltype(v2)>vector<int> &&

因此,您仍然不会区分两种不同形式的g

实际上,如评论中所述,根本不可能致电g。每个电话都会模棱两可。在过载分辨率中,直接参考绑定是一种身份转换。类型T的XVALUE参数是参数T的平等匹配,与T&&一样。(同样,类型T的LVALUE参数将是参数T的平等匹配。

)。

可以超载g具有LVALUE与RVALUE重载。但是您也需要更改v1的初始化:

void g(vector<int> const &) {}
void g(vector<int> &&) {}
// ...
auto const& v1 = f();
auto&& v2 = f();
g( std::forward<decltype(v1)>(v1) );
g( std::forward<decltype(v2)>(v2) );