2017-08-17 28 views
10

爲什麼這個代碼有效?與c++14在主函數中聲明的C++結構體

// Example program 
#include <iostream> 
#include <string> 
using namespace std; 


auto fun() 
{ 
    struct a 
    { 
     int num = 10; 
     a() 
     { 

      cout << "a made\n"; 
     } 
     ~a() 
     { 
      cout << "a destroyed\n"; 
     } 
    }; 
    static a a_obj; 
    return a_obj; 
} 


int main() 
{ 
    auto x = fun(); 
    cout << x.num << endl; 

} 

是怎樣的類型a主可見?如果我更改auto x=a x=它顯然不能編譯,但主要知道類型a

static聲明有,因爲我試圖測試其他的東西,但後來我偶然發現了這種行爲。

運行在這裏:https://wandbox.org/permlink/rEZipLVpcZt7zm4j

+0

它知道是因爲'fun'的返回類型,它被推斷爲'struct a'。 – nwp

+0

如果我從'auto x ='更改爲'a x =',它不會編譯,爲什麼'auto'有效? – PYA

+0

Becouse編譯器會在編譯時推導出返回的變量,所以他知道它會是'struct a'。如果你使用'a x =',編譯器不會知道這個數據類型,因爲它在另一個作用域中被聲明。 –

回答

12

直到你意識到這一點,這一切都令人驚訝:名稱可見性不隱藏類型。它只是隱藏了這個類型的名稱。一旦你明白了這一切都是有道理的。

我可以告訴你這一點沒有auto,只用普通的舊模板:

auto fun() 
{ 
    struct Hidden { int a; }; 

    return Hidden{24}; 
} 

template <class T> auto fun2(T param) 
{ 
    cout << param.a << endl; // OK 
} 

auto test() 
{ 
    fun2(fun()); // OK 
} 

如果你仔細觀察,你會看到這是同樣的情況你:

你有一個結構Hidden這是當地的fun。然後你使用Hidden類型的對象內test:你叫fun返回一個Hidden OBJ,然後你把這個對象傳遞給fun2這反過來又一點問題都沒有使用對象Hidden在所有它的榮耀。

as @Barry建議當您從類中返回一個私有類型的實例時會發生同樣的情況。所以我們從C++ 03開始就有這種行爲。你可以自己嘗試。

+0

甚至可以在C++ 03中用返回私有類型的實例來完成同樣的事情。 – Barry

+0

另一個例子是lambda表達式,它從來沒有名字,但往往只是結構與'運營商()'。 – rustyx

1

C++ 14被製成越來越寬容與auto。你的問題並不清楚,因爲你沒有說明問題所在。

現在我們以不同的方式處理您的問題:爲什麼它不適用於a x = ...

原因是struct定義不在main的範圍內。現在,這會工作:

// Example program 
#include <iostream> 
#include <string> 
using namespace std; 

struct a 
{ 
    int num = 10; 
}; 

auto fun() 
{ 
    static a a_obj; 
    return a_obj; 
} 


int main() 
{ 
    a x = fun(); 
    cout << x.num << endl; 

} 

現在,這裏也沒關係您是否使用aauto,因爲amain()可見。現在auto是一個不同的故事。編譯器問:我是否有足夠的信息來推斷(毫不含糊地)x的類型是什麼?答案是肯定的,因爲a沒有其他選擇。

+0

我知道爲什麼你的代碼工作運行它,我只是在考驗看到的東西當結構是一個功能,但事實上,'auto'能「猜測」是一種可怕的我:( – PYA

+1

@pyjg「猜測」是一個錯誤的詞。它要麼毫無疑問知道或者它給你一個錯誤有沒有猜測參與其中。 – nwp

+0

@pyjg其實對於我來說,這是離奇它無法檢測它在C++ 98/03。爲什麼不呢?有沒有在決定型絕對沒有歧義,那麼爲什麼要創建一個編譯錯誤?這在C++ 14。 –