【问题标题】:What does `auto &&i = foo();` mean`auto &&i = foo();` 是什么意思
【发布时间】:2014-05-06 11:05:50
【问题描述】:

请解释与移动语义一起使用时自动类型推导的工作原理:

#include <iostream>

template <typename T>
struct A {
    static void type() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

float& bar() {
    static float t = 5.5;
    return t;
}

int foo() {
    return 5;
}

int main() {
    auto &&a1 = foo();  // I expected auto -> int    (wrong)
    auto &&a2 = bar();  // I expected auto -> float& (correct)

    A<decltype(a1)>::type();
    A<decltype(a2)>::type();
}

输出是:

static void A<T>::type() [with T = int&&]
static void A<T>::type() [with T = float&]

【问题讨论】:

  • 您的输出显示intfloat?

标签: c++11


【解决方案1】:

auto&amp;&amp;(就像函数模板的参数中的T&amp;&amp;,其中T 是该函数模板的模板参数)遵循与其他推导略有不同的规则 - 它被非正式地称为“通用引用”。

这个想法是,如果初始化器是X 类型的左值,则auto 被推导出为X&amp;。如果它是X 类型的右值,则auto 被推导出为X。在这两种情况下,&amp;&amp; 都会正常应用。根据引用折叠规则,X&amp; &amp;&amp; 变为 X&amp;,而 X &amp;&amp; 仍为 X&amp;&amp;

这意味着在您的a1 情况下,auto 确实被推导出为int,但是a1 然后自然地声明为int&amp;&amp;,这就是decltype(a1) 给你的。

同时a2中的autofloat&amp;a2的类型也是如此,decltype(a2)再次确认。

换句话说,您对第一种情况下auto -&gt; int 的期望是正确的,但a1 的类型是auto &amp;&amp;a1,而不仅仅是auto a1

【讨论】:

  • 对于推导出为“type &&”的变量有什么我应该注意的吗,或者它们是否总是表现为“type”? (在本例中,“int&&”的行为始终与常规 int 相同)
  • @Allan 如果它是从纯右值初始化的,我想不出任何可以区分的东西(decltype 除外)。但是,如果它所指的东西可以改变,您将通过 int&amp;&amp; 引用观察到变化,但您不会通过 int 复制。
【解决方案2】:

auto &amp;&amp;a1 = foo();

foo() 的返回类型是 int。由于您将 a1 声明为 auto&amp;&amp;,它会扩展为 int&amp;&amp;,这就是您对 a1 类型的结果。

auto &amp;&amp;a2 = bar();

bar() 的返回类型是 float&。由于您将 a2 声明为 auto&amp;&amp;,它会扩展为 float&amp; &amp;&amp;,然后按照规则转换为 float&amp;

This answer 解释了通用引用如何扩展的规则:

&& -> &&
&& & -> &
& && -> &
&& && -> &&

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 2014-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多