2013-01-03 150 views
6

我想知道一點關於在C namespaceusing ++基本上我想知道的差異,並找出如何以最好的方式使用它。C++名稱解析

當我看到它有(至少)三種方式來解決一類的名字,我不知道如何選擇其中:

  1. using namespace <namespace>
  2. using <namespace>::<what_to_use>
  3. <namespace>::<what_to_use> <use_it>

我想知道的優點,特別是如果有涉及一個或其他方式表現,如果它只是句法和我偏好東北黑鈣土或者有其他的事情我還沒有這方面考慮。

+1

它與運行時性能無關。 –

+1

我在大學時被告知,除了範圍內的所有名稱空間外,使用'using namespace std;'也是一個安全隱患。 –

+1

1.因爲你描述的原因而氣餒2.幫助你在ADL的幫助下使用他人提供的函數(參見'std :: swap',儘管讓答案更好地向你解釋這一點)3。我最喜歡的,但這是一個味道的問題,如果你不喜歡在所有地方看到「std ::」,那麼可能會很麻煩。但他們都沒有任何性能差異,它們只是名稱解析,並沒有*「編譯成實際的代碼」*。 –

回答

5

首先是using namespace directive,它彙集了來自於當前的命名空間指定的命名空間的所有符號名稱,不論你是否需要/使用它們。當然是不可取的。

二是using namespace declaration。它只會在您當前的命名空間中引入指定的符號名稱。好處是,你不必鍵入完全合格的名稱每次。

三是標準名稱的符號。缺點是,你必須到處都用符號輸入完全合格的名稱。

顯然,二&三是比較適合的。它們之間沒有性能差異。唯一的區別是你輸入的字符數量。簡單地說,根據你的編碼標準的具體情況來選擇。

編輯:
作爲@Jerry所指出的,在與ADL(參數依賴查找)組合使用聲明可以導致不期望的效果。
你可以找到自己的答案一個一個詳細的解釋:

Detailed explanation on how Koenig lookup works with namespaces and why its a good thing?

下的部分,
爲什麼柯尼希算法的批評?

+0

我很喜歡*使用名稱空間聲明*,因爲我可以把它放在我的.cpp文件中,而且我有一個列表,我在其中看到「這是從這個文件中的這些名稱空間使用的」,但我也有*完全限定名字*,因爲他們告訴我,只要我看到他們說這個功能來自這個名字空間。但是,好吧,我想我是在做某種混合的事情,並且從我得到的答案中我感到安全。感謝您花時間解釋這一點。 – qrikko

+1

@qrikko:通常會按組織的編碼標準進行。否則,這是個人選擇。重要的是一旦你做出選擇,就要保持一致。 –

+0

@qrikko:不幸的是,如果你通讀了我的答案,你會意識到1)你不像你想象的那麼安全,2)所有聲稱不會對性能產生任何影響的答案是(間接的)至少可能是錯誤的。他們是正確的,你指定名稱的形式並不直接影響績效,但仍然錯誤地表示(甚至暗示)績效不會受到影響。 –

0

主要的原因是,它可能會導致歧義(包括編譯器和人類閱讀器),它也可以放緩編譯本身(但是這不是大問題,因爲第一件事)

2

有沒有性能無論如何獲得或懲罰。所有調用和變量都在編譯時解析。

三者之間的選擇有點主觀。是的,using namespace <ns>;有時被污染的全球命名空間,,但我認爲它是安全的使用小文件。

我傾向於使用第二個用於測試目的的地方,但我期望發生衝突,但之後我會將其刪除。這可以讓混亂,因爲你可以用兩個合格和未合格名的組合結束了:

vector<std::string> x; 

因爲你有一個using std::vector;在頂部,而不是using std::string;

我是第三位。

1

對代碼的性能沒有影響,這純粹是編譯時的事情。它可能(理論上)對編譯時間有一些影響,但我懷疑它會達到可測量的比例。

using namespace std(或任何其他名稱空間)肯定要避免在頭文件中,頭文件可以包含在任何地方,並在其中引入符號可能會導致含糊不清。

通常,名稱空間的存在是爲了避免名稱衝突,並且using namespace破壞了這一目的。 using the_namespace::some_id也是如此,程度較低。有沒有明確的回答你的問題,但我一般遵循以下規則:

  1. 決不using namespace在頭文件。
  2. 避免using namespaceusing,除非它可以節省大量的打字。如有必要,使用名稱空間別名(即,namespace abbrv = some_really::long_and::nested_namespace;)。
  3. 嘗試限制using的範圍:您可以將其放入函數和塊以及命名空間範圍。也就是說,如果您的.cpp文件中有日誌記錄功能,請將using std::cout;using std::endl;(或您正在使用的任何內容)放入函數體中,而不是放入文件範圍。
4

有一個(當然,有些少見)情況,即你使用真正的形式可以有所作爲,而且要使用形式爲using namespace foo,它的最普遍應用於std命名空間(也就是說,你寫using namespace std;

最明顯的例子是,你寫一個排序的用戶定義類型,它是可能,這將被應用到該用戶還定義了一個類型的擁有swap

如果用戶想要使用swap,如果他們已經定義了swap,就會陷入困境,但如果他們沒有定義,則使用std :: swap。如果您在代碼中直接使用std::swap,那麼即使類型具有自己定義的交換,您也將最終使用std::swap。相反,如果您直接爲該類型指定一個交換,並且沒有提供交換,則代碼將無法編譯。

要解決這個問題,你做這樣的事情:

using namespace std; 

template <class Iter> 
void my_sort(Iter first, Iter last) { 
    // ... 
    if (*last < *first) 
     swap(*first, *last); 
} 

這將找到交換專門針對類型進行比較(即,在同一個命名空間作爲類型定義的swap),如果有一個(通過依賴於參數的查找)和std::swap(如果沒有爲該類型定義)(通過using namespace std;)。

這可能會對性能產生影響 - 如果他們專門爲它們的類型編寫了交換,那麼通常可以預期這是因爲通過這樣做,它們可以提供更好的性能。這意味着明確指定std::swap可能會起作用,但可能會導致性能下降。 (除了上面的情況,我在寫代碼的時候),我更喜歡給出全名(例如,std::swap)至少有兩種可能性可能是首選,我想給編譯器足夠的餘地來選擇正確的。

另一次我發現使用有用的聲明/指令時,命名空間得到真正深層嵌套。 Boost(對於一個明顯的例子)有一些名稱,如果您每次使用完全限定的名稱,那麼這些名稱會太方便使用。對於(現在感謝,主要是過時的)Boost Lambda庫來說尤其如此,在這裏你使用了像_1這樣的佔位符,它最終會像boost::lambda::placeholders::_1一樣(但是我要從內存中去掉,所以這可能至少部分是錯誤的)如果你堅持使用完全合格的名字。這將首先破壞使用lambda庫的大部分目的。

+0

我相信這裏增加了一些有價值的信息。要考慮的事情,因爲它實際上**做**在這些情況下選擇哪一個。感謝您提出。 – qrikko

+2

然而,我會說,在這種情況下,你更願意使用'使用std :: swap;' –