#pragma ปลอดภัยครั้งหนึ่งเคยมีผู้พิทักษ์หรือไม่


310

ฉันได้อ่านแล้วว่ามีการเพิ่มประสิทธิภาพคอมไพเลอร์เมื่อใช้งาน#pragma onceซึ่งอาจทำให้การรวบรวมเร็วขึ้น ฉันรู้ว่าไม่เป็นมาตรฐานและอาจก่อให้เกิดปัญหาความเข้ากันได้ข้ามแพลตฟอร์ม

นี่เป็นสิ่งที่สนับสนุนโดยคอมไพเลอร์ที่ทันสมัยที่สุดบนแพลตฟอร์มที่ไม่ใช่ windows (gcc) หรือไม่?

ฉันต้องการหลีกเลี่ยงปัญหาการรวบรวมแพลตฟอร์ม แต่ยังต้องการหลีกเลี่ยงการทำงานพิเศษของการ์ดสำรอง:

#pragma once
#ifndef HEADER_H
#define HEADER_H

...

#endif // HEADER_H

ฉันควรจะกังวลหรือไม่ ฉันควรจะใช้พลังงานทางจิตเพิ่มเติมในเรื่องนี้หรือไม่?


3
หลังจากถามคำถามที่คล้ายกันฉันพบว่า#pragma onceดูเหมือนจะหลีกเลี่ยงปัญหามุมมองระดับหนึ่งใน VS 2008 ฉันอยู่ในกระบวนการกำจัดยามรวมและแทนที่พวกเขาทั้งหมดด้วย#pragma onceเหตุผลนี้
SmacL

คำตอบ:


188

การใช้#pragma onceควรทำงานกับคอมไพเลอร์สมัยใหม่ แต่ฉันไม่เห็นเหตุผลที่จะไม่ใช้ตัว#ifndefป้องกันมาตรฐาน มันใช้งานได้ดี ข้อแม้หนึ่งคือ GCC ไม่สนับสนุน#pragma onceก่อนรุ่น 3.43.4

ฉันยังพบอีกว่าอย่างน้อยใน GCC จะจดจำมาตรฐาน#ifndefรวมถึงการ์ดป้องกันและปรับให้เหมาะสมดังนั้นจึงไม่ควรช้ากว่า#pragma onceนี้มากนัก


12
ไม่ควรช้าลงเลย (กับ GCC)
เจสันโคโค่

54
มันไม่ได้ถูกนำไปใช้ในทางนั้น แต่ถ้าไฟล์เริ่มต้นด้วย #ifndef ในครั้งแรกและลงท้ายด้วย #endif, gcc จะจดจำไฟล์นั้นและจะข้ามสิ่งที่รวมไว้ในอนาคตโดยไม่รบกวนการเปิดไฟล์
เจสันโคโค่

10
#pragma onceโดยทั่วไปจะเร็วกว่าเนื่องจากไฟล์ไม่ได้รับการประมวลผลล่วงหน้า ifndef/define/endifต้องการ preprocessing ต่อไปเพราะหลังจากบล็อกนี้คุณสามารถมีบางสิ่งที่คอมไพล์ได้ (ในทางทฤษฎี)
Andrey

13
เอกสาร GCC เกี่ยวกับการเพิ่มประสิทธิภาพมาโครป้องกัน: gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html
เอเดรียน

38
หากต้องการใช้ยามรวมมีข้อกำหนดพิเศษที่คุณต้องกำหนดสัญลักษณ์ใหม่เช่น#ifndef FOO_BAR_Hปกติสำหรับไฟล์เช่น "foo_bar.h" หากภายหลังคุณเปลี่ยนชื่อไฟล์นี้คุณควรปรับยามรวมให้สอดคล้องกับอนุสัญญานี้หรือไม่? นอกจากนี้หากคุณมี foo_bar.h สองแห่งที่แตกต่างกันสองแห่งในรหัสต้นไม้ของคุณคุณต้องคิดถึงสัญลักษณ์ที่แตกต่างกันสองแบบสำหรับแต่ละอัน คำตอบสั้น ๆ คือการใช้#pragma onceและถ้าคุณต้องการคอมไพล์ในสภาพแวดล้อมที่ไม่รองรับจริง ๆ ให้ไปข้างหน้าและเพิ่มยามรวมสำหรับสภาพแวดล้อมนั้น
Brandin

329

#pragma once มีหนึ่งข้อเสียเปรียบ (นอกเหนือจากที่ไม่ได้มาตรฐาน) และนั่นคือถ้าคุณมีไฟล์เดียวกันในสถานที่ที่แตกต่างกัน (เรามีสิ่งนี้เพราะระบบสร้างของเราคัดลอกไฟล์ไปรอบ ๆ ) จากนั้นคอมไพเลอร์จะคิดว่าเป็นไฟล์ที่แตกต่างกัน


36
แต่คุณสามารถมีสองไฟล์ที่มีชื่อเดียวกันในสถานที่ต่างกันโดยไม่ต้องสร้าง #define NAMES ที่แตกต่างกันซึ่งเป็น iften ในรูปแบบของ HEADERFILENAME_H
Vargas

69
คุณยังสามารถมีไฟล์สองไฟล์ขึ้นไปที่มี #define เดียวกันซึ่งทำให้ไม่สนุกซึ่งเป็นเหตุผลที่ฉันชอบใช้ pragma หนึ่งครั้ง
Chris Huang-Leaver

107
ไม่โน้มน้าวใจ ... เปลี่ยนระบบการสร้างเป็นระบบที่ไม่ได้คัดลอกไฟล์ แต่ใช้ symlink แทนหรือรวมไฟล์เดียวกันจากที่เดียวเท่านั้นในแต่ละหน่วยการแปล เสียงเหมือนโครงสร้างพื้นฐานของคุณเป็นระเบียบที่จะต้องจัดระเบียบใหม่
Yakov Galka

3
และถ้าคุณมีไฟล์ต่าง ๆ ที่มีชื่อเดียวกันในไดเรกทอรีต่างกันวิธี #ifdef จะคิดว่าไฟล์นั้นเป็นไฟล์เดียวกัน ดังนั้นจึงมีข้อเสียเปรียบสำหรับหนึ่งและมีข้อเสียเปรียบสำหรับอื่น ๆ
rxantos

3
@rxantos หากไฟล์ต่างกัน#ifdefค่าแมโครก็อาจแตกต่างกันเช่นกัน
Motti

63

ฉันหวังว่า#pragma once(หรืออะไรทำนองนั้น) จะอยู่ในมาตรฐาน การรวมเจ้าหน้าที่รักษาความปลอดภัยไม่ใช่เรื่องใหญ่จริง (แต่ดูเหมือนว่าเป็นการยากที่จะอธิบายให้ผู้คนเรียนรู้ภาษา) แต่ดูเหมือนจะเป็นเรื่องน่ารำคาญเล็กน้อยที่สามารถหลีกเลี่ยงได้

ในความเป็นจริงตั้งแต่ 99.98% ของเวลา#pragma onceพฤติกรรมเป็นพฤติกรรมที่ต้องการมันจะดีถ้าป้องกันหลายรวมของส่วนหัวได้รับการจัดการโดยอัตโนมัติโดยคอมไพเลอร์ด้วย#pragmaหรือสิ่งที่จะช่วยให้คู่รวม

แต่เรามีสิ่งที่เรามี (ยกเว้นว่าคุณอาจไม่มี#pragma once)


48
สิ่งที่ฉันต้องการจริงๆคือ#importคำสั่งมาตรฐาน
John

10
คำสั่งการนำเข้ามาตรฐานกำลังมา: isocpp.org/blog/2012/11/… แต่ยังไม่ถึงที่นี่ ฉันขอสนับสนุนเป็นอย่างยิ่ง
AHelps

6
@ Aahelps Vaporware เป็นเวลาเกือบห้าปีแล้วหรือยัง บางทีในปี 2023 คุณจะกลับมาที่ความคิดเห็นนี้และพูดว่า "ฉันบอกคุณแล้ว"
doug65536

มันไม่ใช่ไอ แต่เป็นเพียงขั้นตอนทางเทคนิคเท่านั้น โมดูลถูกนำไปใช้ใน Visual Studio 2015 ( blogs.msdn.microsoft.com/vcblog/2015/12/03/… ) และใน clang ( clang.llvm.org/docs/Modules.html ) และการนำเข้าไม่ใช่ #import
AHelps

ควรทำให้เป็น C ++ 20
Ionoclast Brigham

36

ฉันไม่รู้เกี่ยวกับประโยชน์ด้านประสิทธิภาพใด ๆ แต่มันก็ใช้งานได้ดี ฉันใช้มันในทุกโครงการ C ++ ของฉัน (อนุญาตให้ฉันใช้คอมไพเลอร์ MS) ฉันคิดว่ามันมีประสิทธิภาพมากกว่าการใช้

#ifndef HEADERNAME_H
#define HEADERNAME_H
...
#endif

มันทำงานเดียวกันและไม่ได้เติมพรีโพรเซสเซอร์ด้วยมาโครเพิ่มเติม

GCC สนับสนุน#pragma onceอย่างเป็นทางการในฐานะของรุ่น 3.4


25

GCC รองรับ#pragma onceตั้งแต่ 3.4 ดูhttp://en.wikipedia.org/wiki/Pragma_onceสำหรับการสนับสนุนคอมไพเลอร์เพิ่มเติม

ข้อเสียใหญ่ที่ฉันเห็นในการใช้#pragma onceเมื่อเทียบกับยามรวมคือการหลีกเลี่ยงข้อผิดพลาดการคัดลอก / วาง

ลองดูสิ: พวกเราส่วนใหญ่แทบจะไม่เริ่มต้นไฟล์ส่วนหัวใหม่ตั้งแต่ต้น แต่เพียงแค่คัดลอกไฟล์ที่มีอยู่แล้วแก้ไขตามความต้องการของเรา มันง่ายกว่ามากในการสร้างเทมเพลตที่ใช้งานได้โดยใช้#pragma onceแทนที่จะรวมการ์ด ยิ่งฉันต้องแก้ไขเทมเพลตน้อยฉันก็มีแนวโน้มที่จะพบข้อผิดพลาดน้อยลง การมีตัวป้องกันรวมอยู่ในไฟล์ที่แตกต่างกันนำไปสู่ข้อผิดพลาดของคอมไพเลอร์ที่แปลกและใช้เวลาพอสมควรในการพิจารณาว่าเกิดข้อผิดพลาดอะไร

TL; DR: #pragma onceใช้งานง่ายกว่า


11

ฉันใช้มันและฉันมีความสุขกับมันเพราะฉันต้องพิมพ์ให้น้อยลงเพื่อสร้างส่วนหัวใหม่ มันทำงานได้ดีสำหรับฉันในสามแพลตฟอร์ม: Windows, Mac และ Linux

ฉันไม่มีข้อมูลประสิทธิภาพใด ๆ แต่ฉันเชื่อว่าความแตกต่างระหว่าง #pragma และการป้องกันรวมจะไม่มีอะไรเทียบกับความช้าของการแยกวิเคราะห์ไวยากรณ์ C ++ นั่นคือปัญหาที่แท้จริง ลองคอมไพล์ไฟล์และบรรทัดจำนวนเดียวกันด้วยคอมไพเลอร์ C # เพื่อดูความแตกต่าง

ในท้ายที่สุดการใช้ยามหรือ pragma ไม่สำคัญเลย


ฉันไม่ชอบ #pragma เพียงครั้งเดียว แต่ฉันขอขอบคุณที่คุณชี้ให้เห็นถึงประโยชน์ที่สัมพันธ์กัน ... การแยกวิเคราะห์ C ++ มีราคาแพงกว่าสิ่งอื่นใดมากในสภาพแวดล้อมการทำงาน "ปกติ" ไม่มีใครรวบรวมจากระบบไฟล์ระยะไกลถ้ารวบรวมเวลาเป็นปัญหา
Tom

1
การแยกความช้าของ C ++ อีกครั้งกับ C # ใน C # คุณไม่ต้องแยกวิเคราะห์ (ส่วนใหญ่) LOC นับพันของไฟล์ส่วนหัว (iostream, any?) สำหรับแต่ละไฟล์ C ++ เล็ก ๆ ใช้ส่วนหัวที่คอมไพล์แล้วเพื่อทำให้ปัญหานี้เล็กลงอย่างไรก็ตาม
Eli Bendersky

11

การใช้ ' #pragma once' อาจไม่มีผลใด ๆ (ไม่รองรับทุกที่ - แม้ว่าจะได้รับการสนับสนุนอย่างกว้างขวางมากขึ้น) ดังนั้นคุณต้องใช้รหัสการรวบรวมแบบมีเงื่อนไขอย่างไรก็ตามในกรณีใดทำไมต้องกังวลกับ ' #pragma once' คอมไพเลอร์อาจปรับมันให้เหมาะสมอยู่ดี แต่ขึ้นอยู่กับแพลตฟอร์มเป้าหมายของคุณ หากเป้าหมายทั้งหมดของคุณรองรับคุณควรใช้มันต่อไป แต่มันควรเป็นการตัดสินใจที่มีสติเพราะนรกทั้งหมดจะพังถ้าคุณใช้ pragma และพอร์ตไปยังคอมไพเลอร์ที่ไม่สนับสนุน


1
ฉันไม่เห็นด้วยที่คุณต้องให้การสนับสนุนยามอยู่แล้ว หากคุณใช้ #pragma หนึ่งครั้ง (หรือการ์ด) นี่เป็นเพราะมันทำให้เกิดความขัดแย้งโดยที่พวกเขาไม่มี ดังนั้นหากไม่ได้รับการสนับสนุนจากเครื่องมือลูกโซ่ของคุณโปรเจ็กต์จะไม่คอมไพล์และคุณอยู่ในสถานการณ์ประเภทเดียวกันมากกว่าเมื่อคุณต้องการคอมไพล์ ansi C ในคอมไพเลอร์ K&R เก่า คุณต้องได้รับ chaintool ที่ทันสมัยมากขึ้นหรือเปลี่ยนรหัสเพื่อเพิ่มทหารรักษาพระองค์ การทำลายทั้งหมดจะเป็นอย่างไรหากโปรแกรมรวบรวม แต่ไม่สามารถใช้งานได้
kriss

5

ประโยชน์ด้านประสิทธิภาพมาจากการไม่ต้องเปิดไฟล์อีกครั้งเมื่อ #pragma เคยอ่านแล้ว คอมไพเลอร์จะต้องเปิดไฟล์ (ซึ่งอาจเสียเวลา) เพื่อรับข้อมูลที่ไม่ควรรวมเนื้อหานั้นอีก

นั่นเป็นเพียงทฤษฎีเท่านั้นเพราะคอมไพเลอร์บางตัวจะไม่เปิดไฟล์ที่ไม่มีโค้ดอ่านใด ๆ โดยอัตโนมัติสำหรับชุดรวบรวมแต่ละชุด

อย่างไรก็ตามมันไม่ใช่กรณีของคอมไพเลอร์ทั้งหมดดังนั้น #pragma ที่ควรหลีกเลี่ยงสำหรับโค้ดข้ามแพลตฟอร์มเพราะมันไม่ได้เป็นมาตรฐานเลย / ไม่มีคำจำกัดความและเอฟเฟกต์มาตรฐาน อย่างไรก็ตามในทางปฏิบัติมันดีกว่าการ์ดจริงๆ

ในที่สุดคำแนะนำที่ดีกว่าคุณจะต้องแน่ใจว่าได้ความเร็วสูงสุดจากคอมไพเลอร์ของคุณโดยไม่ต้องตรวจสอบพฤติกรรมของคอมไพเลอร์แต่ละตัวในกรณีนี้คือใช้ทั้ง pragma เพียงครั้งเดียวและการ์ด

#ifndef NR_TEST_H
#define NR_TEST_H
#pragma once

#include "Thing.h"

namespace MyApp
{
 // ...
}

#endif

ด้วยวิธีนี้คุณจะได้รับสิ่งที่ดีที่สุดทั้งสองอย่าง (ข้ามแพลตฟอร์มและช่วยรวบรวมความเร็ว)

เนื่องจากใช้เวลาพิมพ์นานกว่าฉันจึงใช้เครื่องมือเพื่อช่วยสร้างทุกอย่างด้วยวิธีที่รวดเร็ว (Visual Assist X)


Visual Studio ไม่ปรับให้เหมาะสม #include guards as-is? คอมไพเลอร์อื่น ๆ (ดีกว่า) ทำเช่นนั้นและฉันคิดว่ามันค่อนข้างง่าย
Tom

1
ทำไมคุณใส่pragmaหลังจากifndef? มีประโยชน์ไหม?
user1095108

1
@ user1095108 คอมไพเลอร์บางตัวจะใช้ตัวป้องกันส่วนหัวเป็นตัวคั่นเพื่อทราบว่าไฟล์มีรหัสเท่านั้นที่ต้องมีอินสแตนซ์หนึ่งครั้ง หากรหัสบางอย่างอยู่นอกตัวป้องกันส่วนหัวไฟล์ทั้งหมดอาจถูกพิจารณาว่าใช้งานได้มากกว่าหนึ่งครั้ง หากคอมไพเลอร์เดียวกันนั้นไม่สนับสนุน pragma เพียงครั้งเดียวมันจะไม่สนใจคำสั่งนั้น ดังนั้นการวาง pragma หนึ่งครั้งใน guards guards เป็นวิธีทั่วไปที่สุดเพื่อให้แน่ใจว่า guards ส่วนหัวอย่างน้อยสามารถเป็น "optimization"
Klaim

4

ไม่เสมอ.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52566มีตัวอย่างที่ดีของไฟล์สองไฟล์ที่มีความหมายทั้งสองอย่างรวมอยู่ แต่คิดว่าผิดพลาดเหมือนกันเพราะ timestamps และเนื้อหาที่เหมือนกัน (ไม่ใช่ชื่อไฟล์ที่เหมือนกัน) .


10
นั่นจะเป็นข้อบกพร่องในคอมไพเลอร์ (พยายามใช้ทางลัดที่ไม่ควรทำ)
rxantos

4
#pragma onceไม่เป็นมาตรฐานดังนั้นสิ่งที่คอมไพเลอร์ตัดสินใจทำก็คือ "ถูกต้อง" แน่นอนเราสามารถเริ่มพูดคุยเกี่ยวกับสิ่งที่ "คาดหวัง" และสิ่งที่ "มีประโยชน์"
user7610

2

ใช้ gcc 3.4 และ 4.1 บนต้นไม้ขนาดใหญ่มาก (บางครั้งใช้distcc ) ฉันยังไม่เห็นความเร็วใด ๆ เมื่อใช้ #pragma เพียงครั้งเดียวแทนหรือใช้ร่วมกับการ์ดมาตรฐาน

ฉันไม่เห็นว่ามันมีความคุ้มค่าที่อาจทำให้สับสน gcc รุ่นเก่าหรือแม้แต่คอมไพเลอร์อื่น ๆ เนื่องจากไม่มีการประหยัดที่แท้จริง ฉันไม่ได้ลอง de-linters ที่หลากหลายทั้งหมด แต่ฉันยินดีที่จะเดิมพันมันจะทำให้พวกเขาสับสนมาก

ฉันก็หวังว่ามันจะถูกนำมาใช้ในช่วงต้น แต่ฉันสามารถเห็นการโต้แย้ง "ทำไมเราต้องใช้เมื่อ ifndef ทำงานได้อย่างสมบูรณ์แบบ?" เมื่อพิจารณามุมและความซับซ้อนที่มืดมิดของ C รวมถึงยามเป็นหนึ่งในสิ่งที่อธิบายตนเองได้ง่ายที่สุด หากคุณมีความรู้เพียงเล็กน้อยเกี่ยวกับวิธีการทำงานของโปรเซสเซอร์ล่วงหน้าพวกเขาควรอธิบายตนเอง

อย่างไรก็ตามหากคุณสังเกตเห็นความเร็วที่สำคัญโปรดอัปเดตคำถามของคุณ


2

วันนี้โรงเรียนเก่ามีเจ้าหน้าที่รักษาความปลอดภัยเร็วเท่ากับ # pragma หนึ่งครั้ง แม้ว่าคอมไพเลอร์จะไม่จัดการกับมันเป็นพิเศษ แต่ก็ยังคงหยุดทำงานเมื่อเห็น #ifndef WHATEVER และ WHATEVER ถูกกำหนดไว้ วันนี้การเปิดไฟล์สกปรกราคาถูก แม้ว่าจะต้องมีการปรับปรุงมันก็จะอยู่ในลำดับของการ miliseconds

ฉันเพียงแค่ไม่ใช้ #pragma เพียงครั้งเดียวเนื่องจากไม่มีประโยชน์ เพื่อหลีกเลี่ยงการปะทะกันกับยามรวมอื่น ๆ ฉันใช้สิ่งที่ชอบ: CI_APP_MODULE_FILE_H -> CI = ชื่อย่อ บริษัท APP = ชื่อแอปพลิเคชัน; ส่วนที่เหลืออธิบายด้วยตนเอง


19
ประโยชน์ที่พิมพ์ได้น้อยลงหรือไม่
Andrey

1
แต่โปรดทราบว่าบางมิลลิวินาทีหนึ่งแสนครั้งก็เป็นนาที โครงการขนาดใหญ่ประกอบด้วยไฟล์นับหมื่นไฟล์รวมถึงแต่ละหัวข้อด้วย เมื่อพิจารณาจากซีพียูหลายคอร์ในปัจจุบันอินพุต / เอาต์พุตโดยเฉพาะอย่างยิ่งการเปิดไฟล์ขนาดเล็กจำนวนมากเป็นหนึ่งในคอขวดที่สำคัญ
เดมอน

1
"วันนี้โรงเรียนเก่ามีเจ้าหน้าที่รักษาความปลอดภัยเร็วเท่ากับ # pragma หนึ่งครั้ง" วันนี้และเมื่อหลายปีก่อน เอกสารที่เก่าแก่ที่สุดในไซต์ GCC นั้นมีราคา2.95จากปี 2001 และการเพิ่มประสิทธิภาพการรวมผู้พิทักษ์ไม่ใช่เรื่องใหม่ มันไม่ใช่การเพิ่มประสิทธิภาพล่าสุด
โจนาธาน Wakely

4
ประโยชน์หลักคือรวมถึงยามมีข้อผิดพลาดได้ง่ายและใช้คำฟุ่มเฟือย มันง่ายเกินไปที่จะมีไฟล์ต่างกันสองไฟล์ที่มีชื่อเหมือนกันในไดเรกทอรีต่าง ๆ (และตัวป้องกันรวมอาจเป็นสัญลักษณ์เดียวกัน) หรือทำข้อผิดพลาดในการคัดลอกวางในขณะที่คัดลอกรวมการ์ด Pragma เพียงครั้งเดียวก็เกิดข้อผิดพลาดน้อยลงและทำงานบนแพลตฟอร์มพีซีหลักทั้งหมด หากคุณสามารถใช้มันเป็นสไตล์ที่ดีกว่า
AHelps

2

ข้อแตกต่างที่สำคัญคือคอมไพเลอร์ต้องเปิดไฟล์ส่วนหัวเพื่ออ่านการ์ดป้องกัน ในการเปรียบเทียบ pragma ทำให้คอมไพเลอร์ติดตามไฟล์และไม่ทำไฟล์ใด ๆ ของ IO เมื่อเจอไฟล์อื่นรวมถึงไฟล์เดียวกัน แม้ว่ามันอาจฟังดูไม่สำคัญ แต่ก็สามารถขยายโครงการขนาดใหญ่ได้อย่างง่ายดายโดยเฉพาะโครงการที่ไม่มีส่วนหัวที่ดีรวมถึงสาขาวิชา

ที่กล่าวว่าคอมไพเลอร์ในสมัยนี้ (รวมถึง GCC) นั้นฉลาดพอที่จะรักษารวมถึงยามเช่น pragma เพียงครั้งเดียว เช่นพวกเขาไม่เปิดไฟล์และหลีกเลี่ยงโทษ IO ไฟล์

ในคอมไพเลอร์ที่ไม่รองรับ pragma ฉันเห็นการใช้งานด้วยตนเองที่ยุ่งยากเล็กน้อย ..

#ifdef FOO_H
#include "foo.h"
#endif

ฉันชอบ #pragma เมื่อเข้าใกล้เพราะหลีกเลี่ยงความยุ่งยากในการตั้งชื่อการชนและข้อผิดพลาดการพิมพ์ผิด มันเป็นโค้ดที่หรูหรากว่าเมื่อเปรียบเทียบ ที่กล่าวว่าสำหรับรหัสพกพามันไม่ควรเจ็บที่จะมีทั้งคู่เว้นแต่คอมไพเลอร์บ่นเกี่ยวกับมัน


1
"สิ่งที่กล่าวมาวันนี้คอมไพเลอร์ (รวมถึง GCC) ฉลาดพอที่จะรักษารวมถึงยามเช่น pragma ครั้งเดียว" พวกเขาทำมันมานานหลายทศวรรษอาจจะนานกว่าที่#pragma onceมีอยู่!
Jonathan Wakely

คิดว่าคุณเข้าใจฉันผิด ฉันหมายถึงการพูดก่อน pragma หนึ่งครั้งคอมไพเลอร์ทั้งหมดจะต้องมีหลาย penanties IO สำหรับไฟล์ h เดียวกันรวมหลายครั้งในระหว่างขั้นตอน preprocessor การใช้งานแบบสมัยใหม่จบลงด้วยการใช้แคชไฟล์ที่ดีขึ้นในขั้นตอนพรีโปรเซสเซอร์ ไม่ว่าจะไม่มี pragmas ขั้นตอนพรีโปรเซสเซอร์จะยังคงรวมทุกอย่างที่อยู่นอกการ์ดรวม ด้วย pragma เพียงครั้งเดียวไฟล์ทั้งหมดจะถูกทิ้งไว้ จากมุมมองนั้น pragma ยังคงได้เปรียบ
Shammi

1
ไม่ผิดนักคอมไพเลอร์ที่ดีต้องปล่อยทั้งไฟล์โดยไม่ต้อง #pragma อีกครั้งพวกเขาจะไม่เปิดไฟล์เป็นครั้งที่สองและพวกเขาไม่ได้ดูอีกเป็นครั้งที่สองให้ดูที่gcc.gnu.org/onlinedocs/ cpp / Once-Only-Headers.html (นี่ไม่เกี่ยวกับการแคช)
Jonathan Wakely

1
จากลิงก์ของคุณดูเหมือนว่าการเพิ่มประสิทธิภาพเกิดขึ้นเฉพาะใน cpp ไม่ว่าแคชจะเข้ามาเล่น ผู้ประมวลผลล่วงหน้าทราบได้อย่างไรว่ารวมรหัสไว้นอกการ์ด ตัวอย่าง ... extern int foo; #ifndef INC_GUARD #define INC_GUARD คลาส ClassInHeader {}; #endif ในกรณีนี้ตัวประมวลผลล่วงหน้าจะต้องรวม extern int foo ด้วย หลายครั้งถ้าคุณรวมไฟล์เดียวกันหลาย ๆ ครั้ง ในตอนท้ายของวันที่ไม่ได้จุดมากเถียงกันเรื่องนี้ตราบใดที่เราเข้าใจความแตกต่างระหว่าง #pragma ครั้งเดียวและรวมถึงเจ้าหน้าที่รักษาความปลอดภัยและวิธีการคอมไพเลอร์ต่างๆประพฤติกับทั้งสองคน :)
Shammi

1
ไม่ได้ใช้การเพิ่มประสิทธิภาพอย่างชัดเจน
Jonathan Wakely

1

ถ้าเราใช้ msvc หรือ Qt (ถึง Qt 4.5) เนื่องจาก GCC (ไม่เกิน 3.4) MSVC สนับสนุนทั้งฉันสามารถดูเหตุผลที่ไม่ได้ใช้ไม่มี#pragma once#pragma once

ชื่อไฟล์ต้นฉบับมักจะเป็นชื่อคลาสที่เท่ากันและเรารู้ว่าบางครั้งเราต้องการrefactorเพื่อเปลี่ยนชื่อคลาสจากนั้นเราต้องเปลี่ยนมัน#include XXXXด้วยดังนั้นฉันคิดว่าการดูแลรักษาด้วยตนเอง#include xxxxxไม่ใช่งานที่ฉลาด แม้ว่าจะมีส่วนขยาย Visual Assist X แต่การบำรุงรักษา "xxxx" ไม่ใช่งานที่จำเป็น


1

หมายเหตุเพิ่มเติมสำหรับผู้ที่คิดว่าต้องการรวมไฟล์ส่วนหัวอัตโนมัติเพียงครั้งเดียวเท่านั้น: ฉันสร้างตัวสร้างโค้ดโดยใช้ไฟล์ส่วนหัวสองหรือหลายไฟล์รวมกันนับทศวรรษ โดยเฉพาะอย่างยิ่งสำหรับการสร้างโครงร่างห้องสมุดโปรโตคอลฉันพบว่ามันสะดวกสบายมากที่จะมีตัวสร้างโค้ดแบบพกพาที่ทรงพลังและไม่มีเครื่องมือและภาษาเพิ่มเติม ฉันไม่ใช่นักพัฒนาเพียงคนเดียวที่ใช้รูปแบบนี้เนื่องจากX-Macros บล็อกนี้แสดง สิ่งนี้จะเป็นไปไม่ได้หากไม่มีการป้องกันโดยอัตโนมัติ


แม่แบบ C ++ สามารถแก้ปัญหาได้หรือไม่ ฉันไม่ค่อยพบความต้องการใด ๆ ที่ถูกต้องสำหรับมาโครเพราะเทมเพลต C ++ เป็นอย่างไร
ชัดเจน

1
ประสบการณ์มืออาชีพระยะยาวของเราคือการใช้ภาษาซอฟต์แวร์และเครื่องมือโครงสร้างพื้นฐานที่เป็นผู้ใหญ่ตลอดเวลาทำให้เราในฐานะผู้ให้บริการ (ระบบฝังตัว) ได้เปรียบอย่างมากในด้านประสิทธิภาพและความยืดหยุ่น คู่แข่งที่พัฒนาซอฟต์แวร์ระบบฝังตัว C ++ และสแต็คแทนอาจพบว่านักพัฒนาบางส่วนมีความสุขในการทำงานมากขึ้น แต่เรามักจะมีประสิทธิภาพสูงกว่าพวกเขาในเวลาออกสู่ตลาดฟังก์ชั่นและความยืดหยุ่นที่ชาญฉลาดหลายครั้ง Nether ดูถูกดูแคลนผลผลิตเพิ่มขึ้นจากการใช้หนึ่งและเครื่องมือเดียวกันซ้ำแล้วซ้ำอีก Web-Devs จะได้รับผลกระทบจาก Framework ต่างๆมากมาย
Marcel

หมายเหตุ: ไม่รวม guards / # pragma หนึ่งครั้งในทุกไฟล์ส่วนหัวตามหลักการ DRY ฉันเห็นจุดของคุณในX-Macroฟีเจอร์ แต่มันไม่ใช่การใช้งานหลักของการรวมมันไม่ควรเป็นอย่างอื่นเช่นเฮดเดอร์ unguard / # pragma multi ถ้าเราใช้ DRY?
caiohamamura

DRY ย่อมาจาก "อย่าทำซ้ำตัวเอง" มันเกี่ยวกับมนุษย์ เครื่องจักรกำลังทำอะไรไม่มีอะไรเกี่ยวข้องกับกระบวนทัศน์นั้น เทมเพลต C ++ ทำซ้ำได้มากคอมไพเลอร์ C ก็ทำเช่นนั้น (เช่นการวนลูป) และคอมพิวเตอร์ทุกเครื่องทำซ้ำเกือบทุกอย่างที่ไม่น่าเชื่อบ่อยและเร็ว
Marcel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.