不要在標頭檔案中使用using namespace

2021-08-19 16:36:48 字數 2326 閱讀 3687

在這裡,我毫不迴避地說了這句話: 

引用我再也不想在任何標頭檔案中看到「using namespace ***;」了

作為乙個開發者/團隊領導者,我經常會去招聘新的專案成員,有時候也幫助其他組的人來面試應聘者。作為應聘流程之一,我經常要求應聘者寫一些**,因此我檢查過相當多的**。在最近提交的c++**中,我注意到乙個趨勢,在任何標頭檔案中,我總是能看到以下**: 

c++** 

using

namespace std;  

那麼,為什麼我說服了很多c++教材(也許並不是什麼好事),讓他們認為使用上面那段**是非常壞的方式?

讓我們先來看看上面那段**做了什麼。總的來說,

它把命名空間「std」以內的所有內容(或者其他由作者用using呼叫命名空間)無一例外的引入了目前的命名空間中。

請注意我說的「所有內容」,並不是一兩個你想用的類\型別\模板。在一段**的開頭引入命名空間的原因則是加強程式模組化,和減少命名衝突。大體上,它允許你可以寫類似下面的那段**,並且保證編譯器可以選擇正確的實現: 

c++** 

std::vectornames;  

my_cool_reimplementation::vectorothernames;  

現在,假定我們正在嘗試減少**輸入,並且在以上**中使用using宣告(或者更糟糕的,兩個命名空間都宣告了),按照如下**來實現: 

c++** 

vectornames;  

vectorothernames;  

如果這段**的作者很幸運的話,編譯器會選擇vector的正確實現,或者至少在最初的階段會這麼做。

但是過了一段時間,你會碰到一些很奇怪的編譯器錯誤。

幸運的話,你能找到這些錯誤的原因——我曾經遇到過類似問題,我花費了好幾天才能找到這類問題的原因。該死,它們會浪費你很多的時間,僅僅因為你為了想少打5個字元的**。 

並且,如果你把using宣告用在了標頭檔案中,你會讓這類問題更加惡化,因為命名衝突問題早晚都會在乙個呼叫關係非常非常遠的模組中神不知鬼不覺的出現

,而你可能需要查三層呼叫才可以找到原因所在,

乙個標頭檔案包含了另乙個直接使用using宣告的標頭檔案可以導致命名空間被立刻汙染掉,任何乙個使用命名空間的檔案如果使用了std命名空間的內容,都會導致這類問題。

那麼,為什麼你能在很多教科書中看到它們使用using namespace std?我的理論是,它確實會幫助改善整本書的排版,並且能減少一些視覺的混亂。在一本紙質書中,你只有很有限的空間來寫文字,因此你必須最大限度的利用它,加之書中的**例子通常都很簡單。但另一方面,不同的命名空間限定符會帶來了很多視覺混亂,這會讓讀者很難從上下文判斷作者的意圖。當你想在這個時**一些有效率的**的時候,以上兩點都不完全對,現在的編譯器大多數能每行處理60-80個單詞(你可以試試,這可以的)。因此,

不要亂引入命名空間。

如果你非常明確的想在乙個標頭檔案中使用using宣告,應該怎麼做?

我們有其他途徑可以減少不得不用using宣告的情況——你可以用以下其中一種,或則多種方式的組合。 

首先,你只需使用typedef。

我會建議你使用這種方法,即使我並不經常遵循我自己的建議,我也認為無論如何這都是乙個在實際應用中很好的方法。實際上,使用typedef有兩個好處——他讓乙個型別名可讀性增加,如果你選擇了乙個很好的名字,它可以讓作者的意圖更加顯而易見。比較一下如下的宣告方式: 

c++** 

std::maplong> clientlocations;  

typedef std::maplong> clientnametozip;  

clientnametozip clientlocations;  

第二個宣告——即使它被展開為兩行——也比第乙個宣告更加直觀,同時,它也避免了命名空間模糊化。 

另外乙個選擇則是用兩種方法來限制using宣告的作用域——僅僅是你想用的那個「using」符號,例如: 

c++** 

using std::string;  

但是,把這段宣告扔到頭檔案中,幾乎和使用「using namespace」一樣糟糕,因此,你應該使用作用域來限制下它的可見性,來確保你的using宣告真的只在第一次做using宣告的地方有效。例如,你可以用如下方法限制類宣告作用域: 

c++** 

namespace bar  

;  }  

class foo  

;  或者,你可以直接把using的作用域限制到乙個函式中,例如: 

c++** 

void temp()  

不管哪種方法,你都可以把using的作用域限制到需要使用它的**中,而不是把它放到**的公共空間中。

你的工程越大,確保模組化,和最小化不可預料的負面影響就顯得越發重要。 

不要在v for中使用v if

一 前言 以下 寫法,相信80 的初學者寫過,即使沒寫過,也應該見過!v for product in products key product.id v if product.price 50 li ul 使用 v if 來過濾 v for 迴圈的資料是乙個超級大錯誤!儘管這看起來很直觀,但它會導...

不要在 render 方法中使用 HOC

官方介紹 react 的 diff 演算法 稱為協調 使用元件標識來確定它是應該更新現有子樹還是將其丟棄並掛載新子樹。如果從 render 返回的元件與前乙個渲染中的元件相同 則 react 通過將子樹與新子樹進行區分來遞迴更新子樹。如果它們不相等,則完全解除安裝前乙個子樹。例子 下面有兩個計數器,...

不要在MySQL中使用「UTF 8」

mysql 從 4.1 版本開始支援 utf 8,也就是 2003 年,而今天使用的 utf 8 標準 rfc 3629 是隨後才出現的。舊版的 utf 8 標準 rfc 2279 最多支援每個字元 6 個位元組。2002 年 3 月 28 日,mysql 開發者在第乙個 mysql 4.1 預覽版...