[英]C++ Name Resolution
我想知道一點關於namespace
和using
在C ++基本上我想知道的差異,並找出如何以最好的方式使用它。
我看到它有(至少)三種方法來解決類名,我不知道如何選擇它們:
using namespace <namespace>
using <namespace>::<what_to_use>
<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
如此。 您的問題沒有明確的答案,但我通常遵循以下規則:
using namespace
。 using namespace
和using
,除非它可以節省大量的輸入。 必要時使用命名空間別名(即namespace abbrv = some_really::long_and::nested_namespace;
)。 using
:你可以把這個變成功能和模塊,以及命名空間范圍。 也就是說,如果你的.cpp文件中有一個日志功能,那么using std::cout;
並using std::endl;
(或者你正在使用的任何東西)進入函數體,而不是進入文件范圍。 主要原因是它可能導致模糊(編譯器和人類讀者),並且它也可能減慢編譯本身(但這不是首要問題)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.