2010-08-13 27 views
18

Właśnie widziałem to wewnątrz <boost/asio.hpp>Jaki jest powód, dla którego #pragma raz wewnątrz strażników nagłówka?

#ifndef BOOST_ASIO_HPP 
#define BOOST_ASIO_HPP 

#if defined(_MSC_VER) && (_MSC_VER >= 1200) 
# pragma once 
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 

/// .... 

#endif // BOOST_ASIO_HPP 

Pomijając _MSC_VER kontrole preprocesora, jakie są korzyści z posiadania #pragma once w tym przypadku? Czy osłona nagłówka preprocesora nie gwarantuje, że we wszystkich przypadkach i na wszystkich platformach zawartość nagłówka jest tylko raz: included?

Odpowiedz

21

#pragma once określa, że ​​plik zostanie włączony (otwarty) tylko raz przez kompilator podczas kompilowania pliku z kodem źródłowym. Może to skrócić czas kompilacji, ponieważ kompilator nie otworzy się i nie odczyta pliku po pierwszym #include modułu.

Jeśli nie #pragma once, plik będzie otwierany każdorazowo jest ona potrzebna i kompilator przestanie analizowania go na #ifndef BOOST_ASIO_HPP, jeśli został zdefiniowany.

+0

Mówisz, że nagłówek jest otwarty i czytany tylko raz, jeśli mamy #pragma? Nagłówki oznaczają, że plik jest zawsze otwierany, ale zawartość w obrębie wartowników jest pomijana, prawda? Czy moje zrozumienie jest poprawne? Gdybym tylko mógł to zademonstrować, więc to widzę :) – dubnde

+1

W przypadku #pragma raz nie zawsze jest otwarty. Dyrektywa ta powoduje, że kompilator pamięta, aby nie otwierać go ponownie (więcej niż raz). Dlatego ta dyrektywa jest lepsza od #ifndef, którą można pominąć. Jednak wiele osób nadal używa #ifndef do obsługi starych kompilatorów, które nie rozpoznają #pragma raz. –

0

Tak osłony nagłówków zapewniają, że zawartość nagłówka jest uwzględniana tylko raz. ale tutaj używasz #pragma do sprawdzania innej definicji i nie dołączania pliku.

Poniższy link to istniejące pytanie dotyczące osłon głowic w języku SO.

Purpose of Header guards

+1

Osłona nagłówka robi to mimo to, prawda? po co jeszcze raz używać #pragma? – dubnde

+4

Osłona nagłówka mówi preprocesorowi, że musi wyciszyć wszystkie wiersze w pliku z '# ifndef' do' # endif', ale zakłada się, że preprocesor odczytuje cały plik i po prostu nie daje wyniku dla bloku. '#pragma once' mówi preprocesorowi, że jakiekolwiek późniejsze' # include' zawierające ten sam plik należy zignorować. Różnica polega na tym, że w tym ostatnim przypadku preprocesor nawet nie otworzy pliku i nie sprawdzi. Biorąc to pod uwagę, '#pragma once' nie jest standardem, a kompilatory rozwinęły się, aby zrozumieć wzór straży dołączonej i nie powinno być wielkiej różnicy. –

+0

@MeThinks - może nie wszystkie implementacje obsługują tę pragmę, więc nadal chcesz zapobiec przetwarzaniu nagłówka wiele razy. Pragma jest tu dodatkową korzyścią. (komentarz powielony z innej odpowiedzi) – ysap

3
+1

Dlaczego głosowanie w dół? – DumbCoder

+1

ok. Rozumiem ten cel strażników nagłówkowych.Pytanie brzmi, dlaczego mamy strażnika nagłówkowego i pragma jeden – dubnde

+1

@MeThinks - może nie wszystkie implementacje obsługują tę pragmę, więc nadal chcesz zapobiec przetwarzaniu nagłówka wiele razy. Pragma jest tu dodatkową korzyścią. – ysap

0

#pragma once ma ten sam cel, ale obejmuje osłony, które wymagają głębszej analizy, aby zapewnić, że plik jest zawarty dokładnie jeden raz - np.

// somerandomfileinmyproject.cpp 
#undef BOOST_ASIO_HPP 
#include <bost/asio.cpp> 

ile kompilator robi poprawnie obsłużyć takie przypadki, to nadal musi otworzyć plik i przekazać go przez preprocesor, mimo że został włączony wcześniej.

0

można odtworzyć efekt #pragma once w standardowy sposób przy użyciu następujących:

#if !defined GUARD_SYMBOL 
#include "GUARDED_FILE" 
#endif 

chociaż jest dużo bardziej gadatliwy. Jak powiedzieli inni, pomaga to w czasach kompilacji, ponieważ plik nie jest wyszukiwany/otwierany zamiast otwierania pliku i ignorowania wszystkiego w środku - plik wciąż musi zostać przeanalizowany przez preprocesor.

+1

Jak zauważył David, większość współczesnych kompilatorów (szczególnie gcc) rozumie wzór straży nagłówkowej na tyle dobrze, aby pominąć część reparującą, i zachowuje się tak, jakby kiedyś istniała pragma lub tak, jakby kod był napisany tak, jak tu pokazujesz. To, a także fakt, że pragma nie może poprawnie obsłużyć niektórych przypadków narożnych, jest również powodem, dla którego pragma została kiedyś odrzucona w nowy standard C++ 0x. zobacz także [SO disscussion] (http://stackoverflow.com/questions/787533/is-pragma-once-a-safe-include-guard) –