簡體   English   中英

C ++名稱解析

[英]C++ Name Resolution

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

我看到它有(至少)三種方法來解決類名,我不知道如何選擇它們:

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

我想知道優勢,特別是如果有一種或另一種方式涉及性能,如果它只是語法和偏好的問題,或者是否有其他事情我沒有考慮過這個。

首先是using namespace指令 ,它帶來當前命名空間中指定命名空間的所有符號名稱,無論您是否需要/使用它們。 當然不受歡迎。

其次是使用命名空間聲明 它只會在當前命名空間中顯示指定的符號名稱。 優點是您不必每次都輸入完全限定的名稱。

第三個是符號的完全限定名稱 缺點是您必須在使用符號的任何位置鍵入完全限定名稱。

顯然,第二和第三是更合適的。 它們中的任何一個都沒有性能差異。 唯一的區別是您輸入的字符數量。簡單地說,根據您的編碼標准指定選擇。

編輯:
正如@Jerry指出的那樣,將聲明與ADL(基於參數的查找)結合使用會導致不良影響。
你可以在我的一個答案中找到詳細的解釋:

關於Koenig查找如何與命名空間一起工作以及為什么它是一件好事的詳細解釋?

根據該節,
為何批評Koenig算法?

有一種(不可否認,有點不常見)的情況,你使用的形式確實可以產生影響,你想要使用的形式 using namespace foo ,它最常用於std命名空間(即你using namespace std;地方寫的) using namespace std; .

最明顯的例子是您正在為用戶定義的類型編寫一個排序。 可能會應用於用戶也已定義自己的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 (即,在與該類型相同的命名空間中定義的swap ),如果有一個(通過參數依賴查找),則std::swap如果沒有為該類型定義(通過using namespace std; )。

這會對性能產生影響 - 如果他們專門為他們的類型編寫了一個交換,你通常可以期待它,因為通過這樣做,他們可以提供更好的性能。 這意味着明確指定std::swap可能會起作用,但可能會導致性能較差。

否則,它幾乎完全是一個方便和可讀性的問題 - 我主要更喜歡給出全名(例如, std::swap ),除了在上面的情況,其中(在我編寫代碼的時候)至少有兩種可能性是首選,我想給編譯器足夠的余地來選擇正確的。

另一方面,我發現使用聲明/指令很有用的是命名空間真正深度嵌套的時候。 Boost(對於一個明顯的例子)有一些名稱,如果您每次都使用完全限定名稱,那么這些名稱對於方便使用來說太長了。 對於(現在,幸運的是,大多數已經過時)Boost Lambda庫,尤其如此,你使用像_1這樣的占位符,最終會像boost::lambda::placeholders::_1 (但我來自如果你堅持使用完全限定的名字,那么記憶,這可能至少部分是錯誤的。 那將首先打敗使用lambda庫的大部分目的。

沒有任何性能上的提升或懲罰。 所有調用和變量都在編譯時解析。

三者之間的選擇有點主觀。 是的, using namespace <ns>; 有時不贊成污染全局命名空間, 我認為使用小文件是安全的。

我傾向於使用第二個用於測試目的,我預計會發生沖突,但之后我會將其刪除。 這可能會變得更加混亂,因為您最終可能會使用限定名稱和非限定名稱的組合:

vector<std::string> x;

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

我喜歡第三個。

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

在頭文件中肯定要避免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; (或者你正在使用的任何東西)進入函數體,而不是進入文件范圍。

主要原因是它可能導致模糊(編譯器和人類讀者),並且它也可能減慢編譯本身(但這不是首要問題)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM