2011-03-21 55 views
10

#pragma once放在包括衛兵裏面而不是外面有什麼區別嗎?內部和外部雜注之間的區別是否包括警衛?

的情況下1:

#ifndef SOME_HEADER_H 
#define SOME_HEADER_H 
#pragma once 

的情況下2:

#pragma once 
#ifndef SOME_HEADER_H 
#define SOME_HEADER_H 

我只是想知道出於好奇,如果有任何特殊的情況下,我寧願一個或另一個(情況1或情況2)因爲我決定在我的代碼中同時使用(編譯指示和標題保護)。

編輯:

我想你們都誤解了我的問題...我問的pragma once的位置,而不是編譯航班嗎一次頭警衛。

+1

將兩者都包含在內是相當多餘的,你不覺得嗎?我只是使用這些定義來檢查。的 – 2011-03-21 19:15:27

+2

可能重複[曾經的#pragma VS包括警衛?](http://stackoverflow.com/questions/1143936/pragma-once-vs-include-guards) – Jon 2011-03-21 19:27:39

+2

@Tim:他們是在編譯器非冗餘那識別一次「編譯指示」,但不執行gcc所做的巧妙優化,以便在標題保護允許它不會再次訪問文件時識別。至少某些版本的MSVC處於該狀態,不知道最新的。 – 2011-03-21 19:32:46

回答

6

有如果SOME_HEADER_H已經定義被包括在報頭的前面,然後,在第二情況下,預處理器將處理#pragma once在一個微妙的差異,並且在第一它不會。

你會用同樣的TU再次看到一個功能上的差異,如果你#undef SOME_HEADER_H,包括文件:現在

#define SOME_HEADER_H 
#include "some_header.h" 
#undef SOME_HEADER_H 
#include "some_header.h" 

,如果1我有頭文件中的所有定義。在情況2中,我沒有。

即使沒有#undef,由於在情況1中忽略了#pragma once,您可以想象會看到預處理時間的差異。這取決於實施。

我能想到的它可能已經是第一個包含這個頭文件之前定義兩種可能的方式:

  • (明顯的一個),一個完全獨立的文件定義它,無論是故意或意外名稱衝突,
  • 該文件的副本已經定義了它。取決於可能包括這種文件在兩個不同文件名下涉及相同TU的情況的實施方式,例如,由於符號鏈接或文件系統合併。如果你的實現支持#pragma once,並且你仔細檢查它的文檔,你可能能夠找到一個明確的聲明,說明優化是通過包含文件的路徑來應用的,還是通過比較標識文件存儲的東西inode號碼。如果是後者,你甚至可以找出是否仍然存在詐騙行爲,可能被拉扯欺騙預處理,如遠程安裝一個本地文件系統,以掩蓋它的「同一個文件真正」 ...

用於以預期的方式,但是,沒有提供的實施,微軟定義的方式對待#pragma once差異。只要它被處理而不是被跳過,它就會標記包含文件以進行優化,所以無論它是否會在文件中進行第二遍處理都無關緊要 - 第二遍不會發生。

,因爲編譯是非標準的,至少在理論上它可以有不同的實現方式完全不同的含義,在這種情況下,當多少次對其進行處理,可能無關緊要,當然還有。在實踐中,你會認爲沒有人會這樣做。

5

它們是多餘的。

#pragma once不被所有的編譯器支持,而包括守衛者。只需使用包括守衛。像gcc這樣的編譯器足夠聰明,可以理解包括守衛,甚至不會再打開文件。

+1

儘管出於實用目的,所有值得注意的編譯器都支持'#pragma once'。 – zneak 2013-08-13 23:46:53

1

要回答你的問題:

案例1:

編譯器會檢查預處理器常數設置與否,如果沒有定義它,然後檢查的#pragma once指令。這很可能是對字符串「SOME_HEADER_H」的哈希查找,以便在對當前文件名(可能是預處理程序設置的__ FILE __常量)執行另一個哈希查找之前知道它是否已定義。因此,如果該文件從未被讀取過,那麼我們有兩個散列查找和兩個散列保存,如果該文件只被讀取一次散列查找。

案例2:

這顯然是同樣的事情,案例1但是順序相反。所以我們唯一可以比較的是用作查找的散列鍵的長度。根據當前頭文件的路徑(即路徑的長度),#pragma once指令的哈希查找可能會計算更昂貴。如果文件名是「C:\ dude.h」,則比「SOME_HEADER_H」短。

所以我想總結一下。不是。案例1比案例2更有利,反之亦然。至少不叫喊Heureka結束;)

乾杯

相關問題