我一直在尋找通過Google C++ style guide,並遇到了這個:在標準名稱空間中聲明名稱的不良做法?
「不要std下宣佈任何事情,標準庫類的甚至不向前聲明std下聲明實體是不確定的行爲,即,不便於攜帶。要從標準庫中聲明實體,請包含相應的頭文件。「
有人可以解釋這是什麼意思,爲什麼這是未定義的行爲使用示例代碼?
我一直在尋找通過Google C++ style guide,並遇到了這個:在標準名稱空間中聲明名稱的不良做法?
「不要std下宣佈任何事情,標準庫類的甚至不向前聲明std下聲明實體是不確定的行爲,即,不便於攜帶。要從標準庫中聲明實體,請包含相應的頭文件。「
有人可以解釋這是什麼意思,爲什麼這是未定義的行爲使用示例代碼?
有人可以解釋這是什麼意思,爲什麼這是未定義的行爲使用示例代碼?
下面的程序導致未定義行爲:
namespace std {
void foo(int) { }
}
#include <iostream>
int main() {
std::cout << "Hello World!" << std::endl;
}
爲什麼?它在名稱空間std
中聲明名爲foo
的函數。至於爲什麼這可能會導致問題,請考慮:標準庫實現可能有其自己的函數,名稱爲foo()
,可能由<iostream>
中的某個組件使用。您的foo
可能會比標準庫實現的foo
更好。
這是說不要在std
命名空間中聲明自己的類型。您可以使用使用標準庫,但您應該通過包含適當的標頭來完成。
基本上,確保你所有的聲明都在你自己的命名空間中,而不是std
。
他們說你應該從這樣的標準庫不向前申報的東西:
// myheader.h
namespace std{
template<class T>
void SomeStandardFunction();
}
// use std::SomeStandardFunction
相反,你應該只包括直接頭:
// myheader.h
#include <SomeHeaderThatContainsSomeStandardFunction>
// use std::SomeStandardFunction
這並不是說「不要使用標準庫」。
要使用某些東西並聲明某些東西是兩回事。這是說不要聲明任何東西,因爲不要像「class ostream;」那樣做。我想人們以前必須聲明它才能使用它,但現在,因爲事物是在名稱空間std中聲明的,所以只需包含頭文件。
檢查this出。
首先,與Google風格指南中的大部分內容一樣,它實際上是錯誤的。該標準特別允許您在命名空間標準中定義幾個特定的實體(例如,在用戶定義的類型上對現有模板進行專業化)。
但是,忽略這些例外情況,它們確實有正確的總體思路 - 您的代碼通常屬於其他比命名空間標準。你可以把它放在全局命名空間中,或者你可以定義另一個命名空間,但你應該單獨離開std
。
你也應該不是嘗試前向聲明標準庫中的任何東西。標準函數允許(例如)包含額外的參數,只要它們包含默認值,這樣就可以用標準方式調用它們。如果你嘗試自己聲明它們,而不是聲明現有的函數,那麼最終可能會聲明一個模糊的超載。
底線:是的,請使用標準庫。當你使用它時,通過包含標準頭文件來獲取聲明,而不是通過編寫自己的頭文件。
+1擊敗我:「它實際上是錯誤的......現有模板的專業化......」。專門研究'std :: swap <>()'是一種常見和可接受的做法。 「 – wilhelmtell 2011-04-16 01:28:52
+1」首先,**像很多Google風格指南**一樣,實際上是錯誤的。「 – ildjarn 2011-04-16 02:29:42
除了我們做專門'std :: swap <>()'。我們被允許這樣做。 :p – wilhelmtell 2011-04-16 01:30:26
@wilhelmtell:即使那是非常糟糕的形式。最好在與你的類型相同的命名空間中定義一個交換過載,並讓ADL完成查找它的工作。 – ildjarn 2011-04-16 01:40:10
@wilhelmtell:你可以_specialize_'std'模板;你不能_overload_'std'模板。對於'swap',正如@ildjarn所說,首選解決方案是使用可以通過ADL找到的命名空間範圍函數。 C++ 0x通過添加「可交換」概念給予該技術的正式批准。 – 2011-04-16 01:41:46