繁体   English   中英

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

[英]What's the difference between “auto v = f()” and “auto&& v = f()”?

#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是对向量的右值引用。

重载g你已经做的方式是一个非常糟糕的主意。 如果参数是cv不合格的右值,则调用将是模棱两可的,因为两个g都可以接受具有身份转换序列的右值。 据,然而,可以接受的一个过载采取T&另取T&&

如果要转发f()的值类别,请不要像复制到v1一样复制/移动它。 这破坏了价值类别信息。 v1将始终是左值。

此外,您没有正确使用std::forward v1v2都将强制转换为右值引用,并且在这种情况下,在过载解析下的行为将相同。

以下是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(); 使用copy / move构造函数从返回值初始化vector<int> ,将其称为v1 这是一个复制省略上下文。
  • auto&& v2 = f(); 使名称v2指定返回值,并延长了返回值的生存期。

如果编译器确实实现了复制删除,那么这两个代码具有相同的效果。 从C ++ 17开始,使用所谓的“保证复制省略”,这两个代码将相同。

“相同”是指在所有方面都相同,除了下面讨论的decltype(identifier)的结果。


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

std::forward仅在给定了完美转发推论的模板参数(因此可能是引用类型)时才有用。

建议使用decltype decltype(identifier)是一种特殊情况,它会在应用auto推论后重新调用标识符的声明方式。

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

但是现在我们有了:

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

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

实际上,如评论中所述,根本不可能调用g 每次通话都会模棱两可。 在重载解析中,直接引用绑定是一种身份转换。 类型的x值的参数T为参数相等匹配T作为T&& (类似地,类型T的左值参数对于参数TT&相等。)

重载g以实现左值vs.右值重载是可能的。 但是您也需要对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) );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM