2014-01-10 44 views
25

這一方案,當與VC12編譯(在Visual Studio 2013 RTM)[1]導致崩潰(在所有生成配置)的時候,確實不應該:(已知)VC12中的編譯器錯誤?

#include <string> 

void foo(std::string const& oops = {}) 
{ 
} 

int main() 
{ 
    foo(); 
} 

我知道有兩種沉默壞代碼生成臭蟲可能相關:

老實說,我認爲這些是不同的,但。有誰知道

  1. 上是否有連接主動跟蹤錯誤此
  2. 是否有解決方法(或導致該錯誤的情況的明確描述,所以我們可以尋找它/避免在我們的代碼庫中)?

[1]只需創建使用C++控制檯應用程序 '嚮導' 的空項目。爲簡單起見,請禁用預編譯頭文件並保留所有默認值:http://i.stack.imgur.com/rrrnV.png

+2

'return 0;'丟失,但似乎沒有關係... – Mario

+16

@Mario,不需要。也沒有關係。 – sehe

+2

@Sehe https://connect.microsoft.com/VisualStudio/feedback/details/809243/c-11-initializer-lists-as-default-argument?我不知道它是相關還是相關。 – 2014-01-10 12:56:38

回答

8

活動問題已發回November。示例代碼發佈爲:

Compile and run following code in VS2013 

#include <string> 

void f(std::string s = {}) { 
} 

int main(int argc, char* argv[]) { 
    f(); 
    return 0; 
} 

該錯誤已被Microsoft確認。

似乎沒有在那裏發佈解決方法。 編輯解決方法可以很容易地基於避免列表的初始化語法:

void f(std::string s = ""); 
void f(std::string s = std::string()); 
void f(std::string s = std::string {}); 

或者只是老式的(如果你不介意引進過載):

void f(std::string s); 
void f() { f(std::string()); } 
+0

我已經添加了明顯的解決方法。這在某種程度上回答了需要尋找的問題。我想grepping for'= {}'或'{{}',',{}'可以找到出現這種情況的方法。我不完全確信,這將找到(所有)相關的呼叫站點。 – sehe

11

它看起來像Visual Studio只是當它的默認參數是初始值設定項列表時調用哪個構造函數時被破壞。此代碼:

#include <iostream> 

struct test { 
    test() { std::cout << "test()" << std::endl ; } 
    test (int) { std::cout << "test (int)" << std::endl ; } 
}; 

void func(test const &s = {}) 
{ 
} 

int main() 
{ 
    test s = {} ; 
    func() ; 
} 

產生這一結果的gccclang,看到它live here

test() 
test() 

Visual Studio會產生這樣的結果:

test() 
test (int) 

與此代碼:

#include <iostream> 
#include <initializer_list> 

struct test { 
    test() { std::cout << "test()" << std::endl ; }; 

    test (int) { std::cout << "test (int)" << std::endl ; }; 
    test (std::initializer_list<int>) { std::cout << "test (initializer_list<int>)" << std::endl ; } ; 
}; 

void func(test const &s = {0}) 
{ 
} 

int main() 
{ 
    test s = {0} ; 
    func() ; 
} 

gccclang產生這種結果看到它live here

test (initializer_list<int>) 
test (initializer_list<int>) 

Visual Studio產生這個錯誤:

error C2440: 'default argument' : cannot convert from 'initializer-list' to 'const test &' 
    Reason: cannot convert from 'initializer-list' to 'const test' 
    No constructor could take the source type, or constructor overload resolution was ambiguous 

更新

對於一個全面的檢查,我又回到了標準來確保這種差異的根源不存在某種奇怪的規則,或者也許是如此我的限制,使這個代碼不合格。據我所知這個代碼不是不合格。第8.3.5語法特別允許這樣的:

parameter-declaration: 
    attribute-specifier-seqopt decl-specifier-seq declarator 
    attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause 
    [...] 

它似乎並不像部分8.5初始值設定8.3.6默認參數加任何限制,但這種缺陷報告994. braced-init-list as a default argument和工作文件Wording for brace-initializers as default arguments說清楚,它的目的和概述了對該標準所做的更改,並允許它在查看三角洲時沒有明顯限制。

+0

我也會在https://connect.microsoft.com/VisualStudio/feedback/details/809243/c-11-initializer-lists-as-default-argument上發表評論,以防萬一他們需要幫助:/ (好吧,也許他們需要幫助意識到這個bug是破壞性的) – sehe

+1

@sehe添加到bug報告中的評論 –