2012-04-04 57 views
9

考慮一下:顯式初始化指針向量會導致轉換錯誤?

std::vector<int*> v(1, 0); 

編譯沒有用VC++ 10(沒有任何警告,即使在最高警告級別)。但是,它不會在Linux上的mac或gcc上使用llvm進行編譯,並提供了一個錯誤,如「從不兼容的類型const int分配給int *」。我不在尋找解決方案 - 我知道第二個參數是不必要的,或者static_cast修復了錯誤。

我認爲零可以隱式轉換爲任何指針類型。是什麼賦予了?我能做到以下幾點:

int* i = 0; 
int* const& ii = 0; 
const int t = 0; 
i = t; 

據我所知,矢量構造簽名需要const T&,當擴大了vector<int*>成爲int* const&是否正確?有人可以解釋這裏發生了什麼,以及VC++或非VC++編譯器是否正確?

+0

嘗試'nullptr'而不是'0'。 – ildjarn 2012-04-04 19:06:09

+1

您是否將其編譯爲C++ 03或C++ 11程序? – 2012-04-04 19:06:26

+0

與問題無關,但是,爲什麼當[Bjarne說我們應該避免它們]時使用原始指針(http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Keynote-Bjarne-Stroustrup-Cpp11-樣式)? – 2012-04-04 19:10:34

回答

2

這裏看起來像g ++實際上是錯誤的。見C++ 98 23.1.1/9:

對於本節和第21定義的每個序列:

- 所述 構造模板X(InputIterator的樓 InputIterator的升,常量分配器& a = Allocator())

應具有相同的 作用:X(static_cast<typename X::size_type>(f), static_cast<typename X::value_type>(l), a)如果InputIterator是 整數類型。

注意InputIterator是一個模板參數的構造,在這種情況下將是int爲你的榜樣,從而整型。 g ++庫實際上有特定的代碼來處理所有存儲在vector中的類型都是不可或缺的,並且這些都將正常工作。在這種情況下,僅僅因爲您使用0,那麼由標準支配的static_cast實際上是合法的。我試着編譯標準所說的應該等同的代碼,並用g ++ 4.5編譯。

+0

很好的工作。 'std :: vector v(1,0);'編譯就好了。我沒想到MS在這裏是正確的。 – Tabber33 2012-04-04 20:41:28

+0

這取決於實施是否考慮過[Library Issue#438](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#438),它說這不會「工作。建議的解決方案是匹配Tabber失敗的X(static_cast (f),l,a)'。 C++ 11改爲遵循[缺陷報告#1234](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#1234),並再次得到不同的結果。 – 2012-04-04 21:45:33

2

std::vector具有與此簽名

template <class InputIterator> 
vector(InputIterator first, InputIterator last, 
     const Allocator& = Allocator()); 

,如果編譯器扣除InputIterator從您的參數01int(!),將是一個不錯的選擇,但不是做我們想要的一個討厭的構造。

我相信C++ 11要求編譯器努力弄清楚參數是否可以實際爲迭代器。在C++ 03中,它們最終可能會成爲size_type(1)int(0),從而導致您的問題。

整型立即數0可轉換爲空指針,但值爲0的int不是!

+0

謝謝。你是正確的 - 更仔細地看錯誤,我現在看到模板構造函數的實例化在錯誤樹的根部。我只想知道爲什麼VC++(甚至是pre-C++ 11支持)爲了在這裏調用想要的構造函數而額外的「麻煩」,並且違反了語言規則(畢竟,模板化構造函數是更好的匹配)? – Tabber33 2012-04-04 19:47:36

+0

@Bo Persson如果我正確閱讀23.1.1/9,這不是正確答案:g ++實際上錯過了一個特例。 – 2012-04-04 20:13:18