2011-08-25 45 views
0

當我編譯和使用Visual C++ 2010運行此:爲什麼這個仿函數(「lambda」)給出一個奇怪的警告?

#include <iostream> 

int main() { 
    int subtrahend = 5; 

    struct Subtractor { 
     int &subtrahend; 
     int operator()(int minuend) { return minuend - subtrahend; } 
    } subtractor5 = { subtrahend }; 

    std::cout << subtractor5(47); 
} 

我得到正確的答案,42

儘管如此,編譯器會抱怨,這是不可能的:

溫度。 cpp(9):警告C4510:main::Subtractor默認構造函數無法生成
Temp.cpp(6):請參閱聲明main::Subtractor

Temp.cpp(9):警告C4512:main::Subtractor
Temp.cpp(6)賦值運算符不能生成:看到main::Subtractor

Temp.cpp的聲明(9 ):警告C4610:struct main::Subtractor永遠不能被實例化 - 用戶定義構造函數需要

發生了什麼事?

+1

如何獲得'42'作爲答案? 48-5是否等於42? – Nawaz

+0

@Nawaz:哈哈,很好。這是因爲我最初是用48進行測試,但後來我認爲47會是一個更有趣的例子,所以我放下了42個。47在複製/粘貼錯誤期間爬過。 :P – Mehrdad

+0

你爲什麼認爲'47'會是更「有趣」的例子?這有什麼特別之處?你的年齡? :P – Nawaz

回答

4

前兩個警告只是讓你知道,隱式聲明的成員函數無法生成由於參考的數據成員的存在。

第三次警告是a Visual C++ compiler bug

所有這三個警告可以與沒有不良影響可以忽略不計,但你可以很容易地使所有三個通過將基準數據成員的指針,而不是(參考數據成員幾乎從來不值得麻煩)消失。

+1

+1似乎是正確的答案 - 將'int&'更改爲'int'使得第三個警告也消失了!沒想到它是一個錯誤;有趣的是,謝謝... – Mehrdad

0

這是因爲變量subtractor5是一個未命名的結構。如果您想讓錯誤消失,請爲減法器5使用一個名稱。

例如:

struct subtractor { 
: 
} subtractor5 = { subtrahend }; 

可惜我不知道夠不夠C++語言-ESE知道爲什麼它的工作原理,但我不知道爲什麼會發生警告。

+0

我不確定如果我正確理解這一點,但我嘗試用'struct Subtractor {'替換'struct {'並且它沒有改變任何東西。 (剛剛更新了我的問題。) – Mehrdad

+0

有趣。我關注了「未命名」的方面,而不是其餘的錯誤。 –

+0

這裏完全一樣的東西 - 我肯定看到過這個錯誤,關於默認的構造函數/引用變量。由於未命名的問題(由於第三個錯誤),我完全錯過了這種可能性。 – Mehrdad

1

的第一個警告是告訴你一個參考值,不能defaultly構造(引用保證指向某個值)。將減數轉換爲常規整數,問題就會消失。

我敢肯定的第二次警告是類似性質的。

(只是說,它一般是多少最好依賴於類似的boost ::功能或類似的執行(標準:: TR1 ::功能?),而不是手動編寫這些代碼)

+0

我實際上使用的是較舊的編譯器(所以沒有TR1),我只是用VC 2010測試它,以確保它不是編譯器問題(它部分是!)。我試圖遠離Boost,因爲這應該是輕量級的,但無論如何這個想法都是+1。 – Mehrdad

+0

@Ethan:第二個警告確實具有類似的性質。參考文獻不能重新發布,因此您無法分配給它(它將分配給參考文獻)。 –

0

用戶定義的構造函數在下列情況下是必需的:

  • 正在初始化常量數據成員(const int c_member;)。
  • 初始化參考數據成員(int & r_member;
  • 有一個數據成員,其類型沒有默認構造函數。例如:

    class NoDefCtor { public: NoDefCtor(int); };

    class ContainThat { NoDefCtor no_ctor_member; };

  • 繼承自基類,其中基類沒有默認構造函數。幾乎與上面相同(NoDefCtor)。

+0

不要忘記沒有默認構造函數的基類的虛擬繼承。 –

相關問題