2017-08-18 81 views
6
#include <iostream> 

struct Box 
{ 
    Box()   { std::cout << "constructor called" << std::endl; } 
    Box(const Box&) { std::cout << "Copy constructor called" << std::endl; } 
    Box(Box&&)  { std::cout << "Move constructor called" << std::endl; } 
    void run() const { std::cout << "Run" << std::endl;} 
}; 

int main() 
{ 
    Box a(Box()); 
    a.run(); 
} 

demo沒有被稱爲在經過匿名對象作爲參數

在上面的代碼我期待任一Copy ConstuctorMove Constructor到在經過匿名對象Box()作爲參數來調用。但是他們都沒有被召喚。原因可能是copy elision。但是即使是構造函數也不會被要求匿名對象A()。實際上,上面的代碼並沒有編譯和調用run()函數編譯器給出了以下錯誤。

a.cpp: In function ‘int main()’: 
a.cpp:28:7: error: request for member ‘run’ in ‘a’, which is of non-class type ‘Box(Box (*)())’ 
    a.run(); 

因此,當我們輸入Box a(Box())發生了什麼?正在創建什麼?

+3

你被MVP咬了。它認爲'Box a(Box());'是一個名爲'a'的函數聲明,返回一個'Box'。 – Borgleader

+0

@YSC我不確定我是否同意你的格式 - 我更喜歡以前的版本。 – pingul

+1

@pingul較短的代碼傾向於吸引更多的注意力,所以我的編輯沒有(我希望)改變OP的原意。但它絕對是他們的回撥。 – YSC

回答

15

這是Most Vexing Parse的一種情況。當某些東西可以被解析爲一個函數聲明時,它就是。

Box a(Box()) 

是一個名爲a採取Box (*)()類型的函數作爲參數和返回Box函數的聲明。

一種解決方案是使用(新中C++ 11),用於構建您的對象aggregate initialization

Box a{Box{}} 

demo


的MVP在其最簡單的形式中所討論這個計算器的問題Most vexing parse: why doesn't A a(()); work?

如果你確實有一個表達式已驗證。例如:

((0));//compiles 

要了解更多關於語言是如何定義的,和編譯器是如何工作的,你應該瞭解Formal language theory或者更具體Context Free Grammars (CFG)和相關材料,如有限狀態機。如果你對此感興趣,雖然維基百科頁面不夠用,但你必須得到一本書。