2011-12-17 47 views
51

當我使用C++ 11 auto時,關於是否將解析爲值或引用的類型推導規則是什麼?C++ 11「auto」semantics

E.g,有時是明確的:

auto i = v.begin(); // Copy, begin() returns an iterator by value 

這些都是不太清楚:

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? 

回答

58

規則很簡單:它是你如何申報。

int i = 5; 
auto a1 = i; // value 
auto & a2 = i; // reference 

接着例子證明了這一點:

#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 
} 

輸出:

value 
reference 
value 
value 
reference 
value 
+5

請注意,//指針並不是真的必要。另外,僅僅因爲一個編譯器給出這個輸出並不意味着它符合標準。 ;)在這種情況下,它是正確的,儘管可以給出更準確的解釋(推導的類型是「衰減的」)。 – Xeo 2011-12-17 11:22:38

12

§7.1.6.4 [dcl.spec.auto] p6

一旦說明符-ID的類型已經確定d根據8.3,使用聲明者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 

請注意,#1將始終複製傳遞的參數,無論您傳遞引用還是其他任何內容。 (除非你特別指定模板參數,如f<int&>(intref);。)

+0

那麼這對於基於範圍的for循環意味着什麼呢?雖然這意味着它們是通過引用(這對我來說似乎合乎邏輯),但是隻是發現這種情況在一種情況下不會發生。 – leftaroundabout 2012-01-29 21:55:18

+3

@leftaroundabout:這不合邏輯。那裏的`auto'也是一樣的。 `for(auto val:range)`將始終複製,`for(auto&ref:range)`始終是引用。並且,根據'* begin(range)`是否會返回一個值或一個引用,'for(auto && x:range)'會更多地混淆`T &&`或`T&`。 – Xeo 2012-01-29 22:29:02

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 
}