C++ 11"自动"语义

Ale*_*x B 70 c++ c++11

当我使用C++ 11时auto,关于它是否会解析为值或引用的类型推导规则是什么?

例如,有时很明显:

auto i = v.begin(); // Copy, begin() returns an iterator by value
Run Code Online (Sandbox Code Playgroud)

这些不太清楚:

const std::shared_ptr<Foo>& get_foo();
auto p = get_foo(); // Copy or reference?

static std::shared_ptr<Foo> s_foo;
auto sp = s_foo; // Copy or reference?

std::vector<std::shared_ptr<Foo>> c;
for (auto foo: c) { // Copy for every loop iteration?
Run Code Online (Sandbox Code Playgroud)

BЈо*_*вић 82

规则很简单:这是你如何声明它.

int i = 5;
auto a1 = i;    // value
auto & a2 = i;  // reference
Run Code Online (Sandbox Code Playgroud)

下一个例子证明了这一点:

#include <typeinfo>
#include <iostream>    

template< typename T >
struct A
{
    static void foo(){ std::cout<< "value" << std::endl; }
};
template< typename T >
struct A< T&>
{
    static void foo(){ std::cout<< "reference" << std::endl; }
};

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

int main()
{
    int i = 5;
    int &r = i;

    auto a1 = i;
    auto a2 = r;
    auto a3 = bar();

    A<decltype(i)>::foo();       // value
    A<decltype(r)>::foo();       // reference
    A<decltype(a1)>::foo();      // value
    A<decltype(a2)>::foo();      // value
    A<decltype(bar())>::foo();   // reference
    A<decltype(a3)>::foo();      // value
}
Run Code Online (Sandbox Code Playgroud)

输出:

value
reference
value
value
reference
value
Run Code Online (Sandbox Code Playgroud)

  • 请注意,`//指针`并不是必需的.另外,仅仅因为一个编译器提供此输出并不意味着它符合标准.;)在这种情况下它是正确的,虽然可以给出更好的解释究竟发生了什么(推导出的类型是"腐朽的"). (6认同)

Xeo*_*Xeo 13

§7.1.6.4 [dcl.spec.auto] p6

一旦根据8.3确定了declarator-id的类型,使用declarator-id声明的变量的类型是使用模板参数推导的规则从其初始化程序的类型确定的.

这意味着auto在函数调用期间模型模板参数推导除外.

template<class T>
void f(T){} // #1, will also be by-value

template<class T>
void g(T&){} // #2, will always be by-reference
Run Code Online (Sandbox Code Playgroud)

请注意,无论您是传递引用还是其他任何内容,#1将始终复制传递的参数.(除非您特别指定模板参数,如f<int&>(intref);.)

  • @leftaroundabout:这不符合逻辑.`auto`就是一样的.`for(auto val:range)`将始终复制,`for(auto&ref:range)`将始终作为参考.并且要混淆更多`for(auto && x:range)`将是'T &&`或`T&`,这取决于`*begin(range)`是返回值还是引用. (3认同)

qqq*_*qqq 9

无论你从右侧得到什么("=")都不是参考.更具体地说,表达式的结果永远不是参考.在这种情况下,请注意示例中结果之间的差异.

#include <typeinfo>
#include <iostream>

template< typename T >
struct A
{
    static void foo(){ std::cout<< "value" << std::endl; }
};

template< typename T >
struct A< T&>
{
    static void foo(){ std::cout<< "reference" << std::endl; }
};

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

int main()
{
   auto a3 = bar();

   A<decltype(bar())>::foo(); // reference
   A<decltype(a3)>::foo();    // value
}
Run Code Online (Sandbox Code Playgroud)