#Pragma bir zamanlar C ++ 11 standardının bir parçası mı?


140

Geleneksel olarak, C ++ 'da birden fazla başlık eklemesini önlemenin standart ve taşınabilir yolu, makro koruma şeması olarak#ifndef - #define - #endif da adlandırılan derleyici öncesi yönergeler şemasını kullanmaktır (aşağıdaki kod snippet'ine bakın).

#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP
...
#endif

Bununla birlikte, çoğu uygulamada / derleyicide (aşağıdaki resme bakın), makro koruma şeması ile aynı amaca hizmet eden daha "zarif" bir alternatif vardır #pragma once. #pragma oncemakro koruma şemasına kıyasla daha az kod, isim çakışmalarından kaçınma ve bazen daha yüksek derleme hızı gibi çeşitli avantajlara sahiptir.

resim açıklamasını buraya girin

Biraz araştırma yaparak, #pragma oncedirektifin neredeyse tüm bilinen derleyiciler tarafından desteklenmesine rağmen, direktifin #pragma onceC ++ 11 standardının bir parçası olup olmadığı konusunda bir bulanıklık olduğunu fark ettim .

Sorular:

  • Birisi #pragma oncedirektifin C ++ 11 standardının bir parçası olup olmadığını açıklığa kavuşturabilir mi ?
  • C ++ 11 standardının bir parçası değilse, daha sonraki sürümlere dahil etme konusunda herhangi bir plan var mı (örn., C ++ 14 veya üstü)?
  • Birinin tekniklerden birini kullanmanın avantajları / dezavantajları hakkında daha fazla ayrıntıya girmesi de iyi olurdu #pragma once.

9
Bu arada, başlık muhafızları için çift alt çizgi kullanmak standart tarafından yasaklanmıştır, bu da çift alt çizgi ile başlayan tüm sembolleri (diğerlerinin yanı sıra) uygular.
Matteo Italia

9
Önceden bir alt çizgi ve ardından büyük harf kullanılması da engellenir. İkincisi, bulanıklık nerede? Derleyici desteğini görüyorum, standardın bir parçası olduğunu iddia eden kimse görmüyorum?
Yakk - Adam Nevraumont

1
Üçüncü madde işareti için ilgili soruya bakın: #pragma bir kez güvenli bir koruma içerir mi? Başlık muhafızlarının çalıştığı bir durum var, ancak #pragma oncegenellikle çalışmıyor.
user1942027

1
C ++ 11'den bahsetmeden bu soruya cevap vermesi olası yineleniyor .
Yakk - Adam Nevraumont

3
Eh, herhangi bir resmi belgede kodlanmamıştır, ancak bunu fiili standart olarak kabul edebilirsiniz .
Siyuan Ren

Yanıtlar:


107

#pragma onceolduğu değil standart. Kullanılabilen yaygın (ancak evrensel olmayan) bir uzantıdır

  • taşınabilirlikle ilgili endişeleriniz sınırlıysa ve
  • tüm içerme dosyalarınızın her zaman yerel bir diskte olduğundan emin olabilirsiniz.

Standardizasyon için düşünülmüş, ancak güvenilir bir şekilde uygulanamayacağı için reddedilmiştir. (Birkaç farklı uzak bağlantı üzerinden erişilebilen dosyalarınız olduğunda sorunlar oluşur.)

Tek bir gelişme içinde koruma çatışmaları olmadığından emin olmak oldukça kolaydır. Birçok farklı gelişme tarafından kullanılabilen kütüphaneler için, bariz çözüm, oluştururken içerme koruması için çok sayıda rastgele karakter üretmektir. (Yeni bir başlık açtığınızda bunu sizin için yapacak iyi bir editör kurulabilir.) Ancak bu olmadan bile, kütüphaneler arasındaki çatışmalarla ilgili herhangi bir sorunla karşılaşmadım.


11
Sadece uzak montajlar değil. Sert bağlantılar, yumuşak bağlantılar, alt yapılar (Windows'ta). Gerçekten dağınık olabilir.
Tonny

45
Derleyici dosyaları tanımlamak için neden SHA-1 veya MD5 sağlama toplamlarını kullanamıyor?
Sergey

29
Her büyük derleyici destekliyorsa, standartta bir şey koymamanın nedenini gerçekten anlamıyorum. Aslında bu standarttan çok daha az desteklenen şeyler var. Ayrıca, dosya adı çakışmalarının zaten büyük bir sorun olduğu dosyaları da içerdiğimizde, kenar sorunları hakkında şikayet etmek oldukça aptalca görünüyor. % 100 sorunsuz bir özellik için bu talebin genel olarak #included başlık dosyaları kavramına uygulanması iyi olurdu.
TED

38
Kodunuz sembolik bağlantılar veya garip bağlar aracılığıyla farklı konumlardan bazı dosyalar içeriyorsa, zaten taşınabilir değildir. Bu nedenle pragma once, doğal olarak taşınabilir olmayan (ve hatta düşünülmemesi gereken) bir şeyi portatif olarak uygulayamayacağını savunmak , C ++ 'ın baş aşağı dünyasının bir başka saçmalığıdır.
doc

7
@JoseAntonioDuraOlmos Sembolik bağlantıların C ++ dilinin kapsamı dışında bir işletim sistemi özelliği olduğunu kabul ediyorum. Bu nedenle soru, C ++ komitesinin neden dilin kapsamı dışında bir şey düşünmesi gerektiği ortaya çıkıyor? Sorumluluğu olmayan bir şeyi garanti etmeye çalışmak IMO'nun bir anlamı yok. DOS, dosya adı başına yalnızca 8 + 3 karakterleri desteklemiştir, ancak hiç kimse #includekaldırılması gerektiğini savunmamıştır, çünkü yönerge körü körüne kötüye kullanılabilir. #pragma oncederlemeyi kırmak için sembolik bağlantılardan yararlanmamanız koşuluyla, taşınabilirliği hiçbir şekilde kısıtlamaz.
doc

32

Standardın §16.6 Bölümü ( N3936 taslağı) #pragmayönergeleri şu şekilde açıklamaktadır:

Formun bir ön işleme direktifi

# pragma pp-tokensopt new-line

uygulamanın, uygulama tanımlı bir şekilde davranmasına neden olur. Davranış, çevirinin başarısız olmasına veya çevirmen ya da ortaya çıkan programın uygunsuz davranmasına neden olabilir. Uygulama tarafından tanınmayan herhangi bir pragma göz ardı edilir.

Temel #pragma onceolarak bir #pragmadirektifin uygulamaya özel bir örneğidir ve hayır, standart değildir. Hala.

Genellikle GCC ve Clang da dahil olmak üzere çoğu "büyük derleyici" tarafından geniş çapta desteklenir ve bu nedenle içerme korumaları kazan plakasından kaçınılması önerilir.


10
Her ikisini de #pragmave #definebaşlık korumasını yapabileceğinizi unutmayın .
Yakk - Adam Nevraumont

18
"Uygulama tarafından tanınmayan herhangi bir pragma yok sayılır" . Şu mesaj anlamına gelir: Uyarı: tanınmayan pragma yönergesi uygun değil mi?
rodrigo

6
"ve bu nedenle içerme korumaları önlemek için önerilen yol" - çok cesur bir ifade. Bu standart olmayan bir yöntemdir ve bunu kullanmanın yararları azdır ve deneyimlerimle pek alakalı olmamıştır, bu yüzden +1'ımı almak zorunda kaldım.
Alex

19
@Yakk: Eğer birisi #definebaşlık koruyucusu yazarsa , yazmak #pragma onceiçin de bir nedeni yoktur .
Nawaz

5
@Nawaz Bir derleyici, #pragma onced olan her dosyanın (yoldan) önbelleğini tutabilir ve d olması durumunda dosyayı #includeatlayamaz #include(dosyayı bile açamaz). gcc üstbilgi korumaları için de aynısını yapar , ancak çok, çok kırılgandır. Yapması #pragmakolay, başlık koruyucusu zor.
Yakk - Adam Nevraumont
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.