ฉันจะปิดเสียงเตือนเกี่ยวกับตัวแปรที่ไม่ได้ใช้ได้อย่างไร


237

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

อะไรจะเป็นวิธีที่ดีที่สุดในการเขียนโปรแกรมเตือน

#ifdef รอบฟังก์ชั่นหรือไม่

#ifdef _MSC_VER
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal qrLeft, qreal qrTop, qreal qrWidth, qreal qrHeight)
#else
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal /*qrLeft*/, qreal /*qrTop*/, qreal /*qrWidth*/, qreal /*qrHeight*/)
#endif
{

มันน่าเกลียดมาก แต่ดูเหมือนว่าวิธีที่คอมไพเลอร์จะชอบ

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

มีวิธีที่ถูกต้องหรือไม่?


7
ฉันเพิ่งรู้ว่าคุณถามคำถามที่คล้ายกันเมื่อเดือนพฤศจิกายน นี่คือเหตุผลที่มันดูคุ้นเคย! ;) stackoverflow.com/questions/308277/…
อเล็กซ์ B

9
ทำไมไม่เพียงคอมเม้นท์คอมไพเลอร์ทั้งคู่ล่ะ? ถ้าหาเรื่องคือไม่ได้ใช้ในหนึ่งมันอาจจะไม่ได้ใช้ในที่อื่น ๆ ...
โรเจอร์ Lipscombe

12
คุณควรรู้ว่า Qt มีQ_UNUSEDมาโครเพียงแค่นี้ ตรวจสอบในเอกสารประกอบ
Evan Teran

1
โซลูชัน C ทำงานได้ดีใน C ++ เช่นกัน: stackoverflow.com/a/3599170/1904815
JonnyJD

-Wno-unused-parameter อาจเป็นตัวเลือกหากคุณสามารถมีค่าสถานะบิลด์เฉพาะคอมไพเลอร์
Code Abominator

คำตอบ:


327

คุณสามารถใส่มันใน(void)var;นิพจน์ (ไม่ทำอะไรเลย) เพื่อให้คอมไพเลอร์เห็นว่ามันถูกใช้ นี่คือพกพาระหว่างคอมไพเลอร์

เช่น

void foo(int param1, int param2)
{
    (void)param2;
    bar(param1);
}

หรือ,

#define UNUSED(expr) do { (void)(expr); } while (0)
...

void foo(int param1, int param2)
{
    UNUSED(param2);
    bar(param1);
}

22
+1 - ฉันจะทำเอกสารทำไมคุณไม่ใช้ตัวแปรแม้ว่าจะอยู่ที่นั่น
Tobias Langner

18
นี่คือวิธีQ_UNUSEDการใช้งานในหลักการ
Dmitry Volosnykh

11
@Cameron คุณสามารถละเว้นชื่อพารามิเตอร์ใน C ++ หากเป็นเทมเพลตมันจะไม่ถูกใช้ใน C ดังนั้นคุณไม่จำเป็นต้องใช้กลลวงแบบคาสตรอล
Alex B

13
เพียงแค่#define UNUSED(expr) (void)(expr)ควรจะทำงานมากเกินไป (โดยไม่ต้องทำในขณะที่)
JonnyJD

7
ฉันสงสัยว่าจะทำเช่นนั้นได้อย่างไรสำหรับเทมเพลต variadic ในtemplate<typename... Args> void f(const Args&... args)ฉันไม่สามารถเขียน(void)args;หรือ(void)args...;เพราะทั้งคู่มีข้อผิดพลาดทางไวยากรณ์
panzi

101

ใน GCC และ Clang คุณสามารถใช้__attribute__((unused))คำสั่ง preprocessor เพื่อให้บรรลุเป้าหมายของคุณ
ตัวอย่างเช่น:

int foo (__attribute__((unused)) int bar) {
   return 0;
}

1
นี่เป็นทางออกที่ดีที่สุดสำหรับฟังก์ชั่นโทรกลับ
Sonic Atom

1
สนับสนุนโดยเสียงดังกราว: clang.llvm.org/docs/…
Alexander


39

โซลูชันปัจจุบันของคุณดีที่สุด - แสดงความคิดเห็นชื่อพารามิเตอร์หากคุณไม่ได้ใช้ สิ่งนี้ใช้ได้กับคอมไพเลอร์ทั้งหมดดังนั้นคุณไม่จำเป็นต้องใช้ตัวประมวลผลล่วงหน้าเพื่อทำมันเป็นพิเศษสำหรับ GCC


7
เพียงเพื่อเสริมคำตอบนี้ - คุณไม่จำเป็นต้องมี #ifdef เพียงใส่เครื่องหมายชื่อพารามิเตอร์ที่ไม่ได้ใช้
quamrana

4
ฉันมีกรณีที่พารามิเตอร์เป็นส่วนหนึ่งของการติดต่อกลับและแสดงความคิดเห็นออกแบ่งการรวบรวม (ดังนั้นฉันไม่แน่ใจว่าทำไมg++มีการเตือนเกี่ยวกับมัน) ในกรณีเช่นนี้คุณจะแนะนำอะไร
Drew Noakes

1
ลองจินตนาการถึงวิธีเสมือนแบบอินไลน์ด้วยพารามิเตอร์ที่ไม่ได้ใช้ / * ความเห็น * / ลูกค้าของอินเตอร์เฟสจะไม่เห็นชื่อพารามิเตอร์ระหว่างการเติมข้อความอัตโนมัติใน IDEs ส่วนใหญ่ ในกรณีนี้การแก้ปัญหา UNUSED () สะดวกกว่า แต่สะอาดกว่า
cbuchart

ฉันคิดว่าง่ายกว่าดีกว่าการใส่ความคิดเห็นออกมาชัดเจนมาก
fievel

26

การอัปเดต C ++ 17

ใน C ++ 17 เราได้รับคุณลักษณะ[[บางที _unused]]ซึ่งครอบคลุมใน[dcl.attr.unused]

attribute-token บางที _unused บ่งชี้ว่าชื่อหรือเอนทิตีอาจไม่ได้ใช้อย่างตั้งใจ มันจะปรากฏขึ้นมากที่สุดครั้งหนึ่งในแต่ละรายการแอตทริบิวต์และไม่มีแอตทริบิวต์ข้อโต้แย้งจะอยู่ ...

ตัวอย่าง:

 [[maybe_unused]] void f([[maybe_unused]] bool thing1,
                        [[maybe_unused]] bool thing2) {
  [[maybe_unused]] bool b = thing1 && thing2;
    assert(b);
 }

การใช้งานไม่ควรเตือนว่าไม่ได้ใช้ b ไม่ว่าจะมีการกำหนด NDEBUG หรือไม่ก็ตาม - ตัวอย่าง]

สำหรับตัวอย่างต่อไปนี้:

int foo ( int bar) {
    bool unused_bool ;
    return 0;
}

ทั้งเสียงดังกราวและ gcc สร้างการวินิจฉัยโดยใช้-Wall -Wextraสำหรับทั้งแถบและunused_bool ( ดูแบบสด )

ในขณะที่เพิ่ม[[บางทีอาจใช้]]ปิดการวินิจฉัย:

int foo ([[maybe_unused]] int bar) {
    [[maybe_unused]] bool unused_bool ;
    return 0;
}

เห็นมันมีชีวิตอยู่

ก่อน C ++ 17

ใน C ++ 11 รูปแบบทางเลือกของUNUSEDมาโครอาจเกิดขึ้นได้โดยใช้การแสดงออกแลมบ์ดา ( ผ่าน Ben Deane ) ด้วยการจับตัวแปรที่ไม่ได้ใช้:

#define UNUSED(x) [&x]{}()

การร้องขอนิพจน์แลมบ์ดาในทันทีควรได้รับการปรับให้เหมาะสมตามตัวอย่างต่อไปนี้:

int foo (int bar) {
    UNUSED(bar) ;
    return 0;
}

เราเห็นได้ในgodboltว่าการโทรได้รับการปรับให้เหมาะที่สุด

foo(int):
xorl    %eax, %eax
ret

5
ดังนั้นคุณพูดถึง C ++ 11 แล้วจัดการเพื่อนำเสนอแมโคร! อุ๊ย! บางทีการใช้ฟังก์ชั่นน่าจะสะอาดกว่านี้? template <class T> inline void NOTUSED( T const & result ) { static_cast<void>(result); }คุณสามารถใช้แลมบ์ดาในฟังก์ชั่นได้ด้วย
Alexis Wilke

godbolt เป็นแหล่งข้อมูลที่ดี
yano

5
[&x]{}()ไม่ได้เงียบคำเตือนจริงๆ แต่ผ่านการเตือนผ่านจากฟังก์ชั่นโทรไปแลมบ์ดาแทน มันจะใช้เวลานานกว่าคอมไพเลอร์ระบุว่านี่เป็นคำเตือน แต่เสียงดังกราวเรียบร้อยแล้วบ่นเกี่ยวกับตัวแปรที่ไม่ได้ใช้ในรายการจับภาพ
nVxx

25

วิธีที่สะอาดยิ่งขึ้นคือการแสดงความคิดเห็นชื่อตัวแปร:

int main(int /* argc */, char const** /* argv */) {
  return 0;
}

8
สิ่งนี้ไม่ดีถ้าคุณมี doxygen และต้องการบันทึกพารามิเตอร์
Alexis Wilke

18
@AlexisWilke: นั่นจะถือว่าเป็นข้อบกพร่องใน doxygen, IMO
6502

3
คุณสามารถ #dine YOUR_PROJECT_UNUSED (argname) ตามเงื่อนไขบน #ifdef DOXYGEN เพื่อให้ doxygen สามารถเห็นชื่อและตัวแปลที่แท้จริงไม่ผ่าน int main (int YOUR_PROJECT_UNUSED (argc), ... ) ไม่เหลือเชื่อ แต่ใช้งานได้
mabraham

ฉันพบว่ามันเจ็บปวดมากในการใส่เครื่องหมายความคิดเห็นลงในบล็อกของโค้ดที่มีความคิดเห็นซ้อนกันหลายอย่าง (คอมไพเลอร์บ่นทุกเรื่อง)
Jeff McClintock

@JeffMcClintock เพียงใช้ความคิดเห็นบรรทัดเดียว บรรณาธิการที่ดีที่สุดสนับสนุนการแก้ไขบล็อกแนวตั้ง (เช่น [Ctrl] + [V] ใน Vim) มิฉะนั้นให้ใช้#if 0 / #endifความคิดเห็นที่ถูกบล็อก
Ruslan

24

เพื่อนร่วมงานเพิ่งชี้ให้ฉันเห็นมาโครตัวน้อยตัวนี้ที่นี่

เพื่อความสะดวกฉันจะรวมมาโครด้านล่าง

#ifdef UNUSED
#elif defined(__GNUC__) 
# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) 
#elif defined(__LCLINT__) 
# define UNUSED(x) /*@unused@*/ x 
#else 
# define UNUSED(x) x 
#endif

void dcc_mon_siginfo_handler(int UNUSED(whatsig))

12
"nice" "macro" "c ++" - เลือก 2
Jeff McClintock

23

ไม่ได้ตั้งค่าสถานะคำเตือนเหล่านี้ตามค่าเริ่มต้น คำเตือนนี้ต้องถูกเปิดใช้งานอย่างชัดเจนโดยการส่ง-Wunused-parameterไปยังคอมไพเลอร์หรือโดยปริยายโดยการส่งผ่าน-Wall -Wextra(หรืออาจเป็นการรวมกันของธงอื่น ๆ )

คำเตือนพารามิเตอร์ที่ไม่ได้ใช้สามารถถูกยับยั้งได้โดยส่งผ่าน-Wno-unused-parameterไปยังคอมไพเลอร์ แต่โปรดทราบว่าการปิดใช้งานแฟล็กนี้ต้องมาหลังจากการเปิดใช้งานแฟล็กที่เป็นไปได้ใด ๆ สำหรับคำเตือนนี้ในบรรทัดคำสั่งคอมไพเลอร์


2
แม้ว่านี่อาจไม่ใช่คำตอบที่ดีที่สุดสำหรับคำถาม (เนื่องจากคำถามคือวิธีการหลีกเลี่ยงคำเตือนไม่ใช่วิธีปิดใช้งาน) คำตอบนี้อาจเป็นคนที่มาจาก google (เช่นฉัน) กำลังค้นหา ("อย่างไร เพื่อปิดการใช้งานคำเตือนนี้ ") ดังนั้นฉันจึงให้ +1 ขอบคุณสำหรับคำตอบของคุณ!
mozzbozz

13

วิธีแบบไร้แมโครและแบบพกพาเพื่อประกาศพารามิเตอร์อย่างน้อยหนึ่งพารามิเตอร์โดยไม่ได้ใช้:

template <typename... Args> inline void unused(Args&&...) {}

int main(int argc, char* argv[])
{
    unused(argc, argv);
    return 0;
}

ดีมาก แต่โปรดทราบว่าต้องใช้ C ++ 11 (หรือใหม่กว่า)
Paul R

ฉันโหวตคำตอบนี้เพราะฉันไม่ต้องการเสียสละเวลารวบรวม (โดยใช้แม่แบบ) เพียงเพื่อกำจัดคำเตือน
Konrad Kleine

@ KonradKleine: อาจใช้เวลารวบรวมเท่าไหร่ จากการทดสอบบนคอมพิวเตอร์ของฉันฉันสามารถทำการโทรที่ไม่ได้ใช้ () หนึ่งพันครั้งในสิบวินาที
Daniel McLaury

@DanielMcLaury นี่เป็นเพียงการคาดเดาของฉันและฉันยังไม่ได้ทำการทดลองใด ๆ
Konrad Kleine

8

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

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

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


5
"การใช้คำสั่ง preprocessor ถือเป็นสิ่งชั่วร้ายเกือบตลอดเวลา" จริงๆ? โดยใคร?
แกรมเพอร์โรว์

12
โดยทุกคนที่ใส่ใจเกี่ยวกับขอบเขตความสามารถในการแก้ไขข้อบกพร่องอย่างถูกต้องหรือสติของพวกเขา
บิล

2
@ Graeme มันดูไร้เดียงสาเมื่อเราเห็นมันแค่ 4 บรรทัด แต่การแพร่กระจายไปรอบ ๆ นั้นจะทำให้ปวดหัว #ifdef ช่วยให้คุณสามารถใส่ซอร์สโค้ดหลายเวอร์ชันซึ่งคอมไพเลอร์จะเห็นเพียงหนึ่งเวอร์ชันเท่านั้น เช่นเดียวกับ Bill ที่กล่าวถึงมันทำให้การดีบักยากขึ้น ฉันได้อ่านเกี่ยวกับความชั่วร้ายของคำสั่ง preprocessor ในหนังสือและบล็อกที่หลากหลายรวมถึงประสบการณ์ด้วยตัวเอง แน่นอนว่าทุกอย่างนั้นสัมพันธ์กัน บางครั้งคำสั่งของผู้ประมวลผลก่อนจะเข้าใจได้ง่ายเพราะสิ่งอื่น ๆ จะมีผลกระทบที่เลวร้ายกว่าและประเด็นของฉันก็คือที่นี่เท่านั้นที่ควรหลีกเลี่ยงเมื่อเป็นไปได้
Ben Dadsetan

1
การใช้มากเกินไปไม่ดี แต่ฉันจะเรียกว่า#define UNUSED(expr) (void)(expr)เหมาะสม
JonnyJD

7

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

ฉันจะสมมติว่าคุณมีการใช้งานที่แตกต่างอย่างสิ้นเชิงในไฟล์ต้นฉบับ ในกรณีเหล่านี้คุณสามารถแสดงความคิดเห็นพารามิเตอร์ที่ละเมิดหรือเพียงแค่เขียนพารามิเตอร์

ตัวอย่าง:

func(int a, int b)
{
    b;
    foo(a);
}

สิ่งนี้อาจดูเป็นความลับดังนั้นให้นิยามมาโครเช่น UNUSED วิธีที่ MFC ทำคือ:

#ifdef _DEBUG
#define UNUSED(x)
#else
#define UNUSED(x) x
#endif

เช่นนี้คุณเห็นคำเตือนว่ายังอยู่ในการสร้างข้อบกพร่องอาจเป็นประโยชน์


4

ไม่ปลอดภัยที่จะใส่เครื่องหมายชื่อพารามิเตอร์ทุกครั้งหรือไม่ หากไม่ใช่คุณสามารถทำสิ่งที่ชอบ

#ifdef _MSC_VER
# define P_(n) n
#else
# define P_(n)
#endif

void ProcessOps::sendToExternalApp(
    QString sAppName, QString sImagePath,
    qreal P_(qrLeft), qreal P_(qrTop), qreal P_(qrWidth), qreal P_(qrHeight))

มันน่าเกลียดน้อยกว่านิดหน่อย


4
ความจริงที่ว่าชื่อพารามิเตอร์ไม่บังคับใน C ++ - เป็น C - เป็นเพียงเพื่อให้วิธีมาตรฐานและง่ายต่อการป้องกันการเตือน
AProgrammer

1
@ แฮ็คไม่เคยพูดว่ามันเป็น ฉันมักจะชี้ให้เห็นความแตกต่างระหว่าง C และ C ++ โดยเฉพาะอย่างยิ่งเมื่อพวกเขาอยู่ในภูมิภาคที่คุณคิดว่าเป็นส่วนย่อยทั่วไป ... เพียงแค่นิสัยเพราะฉันทำงานในฐานรหัสผสม
AProgrammer

4

ฉันได้เห็นสิ่งนี้แทนที่จะเป็น(void)param2วิธีปิดปากเตือน:

void foo(int param1, int param2)
{
    std::ignore = param2;
    bar(param1);
}

ดูเหมือนว่าจะมีการเพิ่มใน C ++ 11


ดูเหมือนว่าจะทำอะไรไม่ถูกเพิกเฉยหลังจากรวบรวม
GyuHyeon Choi

3

ใช้UNREFERENCED_PARAMETER(p)งานได้ ฉันรู้ว่ามันถูกกำหนดไว้ใน WinNT.h สำหรับระบบ Windows และสามารถกำหนดได้อย่างง่ายดายสำหรับ gcc เช่นกัน (หากยังไม่มีมัน)

UNREFERENCED PARAMETER(p) ถูกกำหนดให้เป็น

#define UNREFERENCED_PARAMETER(P)          (P)

ใน WinNT.h


2

ใช้การตั้งค่าสถานะของคอมไพเลอร์เช่นตั้งค่าสถานะสำหรับ GCC: -Wno-unused-variable


1

คุณสามารถใช้__unusedเพื่อบอกคอมไพเลอร์ว่าอาจไม่ใช้ตัวแปร

- (void)myMethod:(__unused NSObject *)theObject    
{
    // there will be no warning about `theObject`, because you wrote `__unused`

    __unused int theInt = 0;
    // there will be no warning, but you are still able to use `theInt` in the future
}

2
ซึ่งคอมไพเลอร์? เนื่องจาก__unusedไม่ใช่มาตรฐาน C ++ และอื่น ๆ อีกมากมายไม่ว่าคุณจะโพสต์อะไร ... นั่นคือวัตถุประสงค์ ดังนั้นคำตอบนี้มีประโยชน์สำหรับคอมไพเลอร์เฉพาะเท่านั้นและทำให้โค้ดไม่สามารถพกพาได้และในความเป็นจริงไม่ถูกต้องเนื่องจากรหัสผู้ใช้ไม่ได้หมายถึงการใช้ตัวระบุที่ขึ้นต้นด้วย__ซึ่งสงวนไว้สำหรับการนำไปใช้
underscore_d

1

ใน C ++ 11 นี่คือโซลูชันที่ฉันใช้:

template<typename... Ts> inline void Unreferenced(Ts&&...) {}

int Foo(int bar) 
{
    Unreferenced(bar);
    return 0;
}

int Foo2(int bar1, int bar2) 
{
    Unreferenced(bar1, bar2);
    return 0;
}

ตรวจสอบแล้วว่าเป็นแบบพกพา (อย่างน้อยใน msvc ที่ทันสมัยเสียงดังกราวและ gcc) และไม่สร้างรหัสพิเศษเมื่อเปิดใช้งานการปรับให้เหมาะสม ไม่มีการเพิ่มประสิทธิภาพการเรียกใช้ฟังก์ชันพิเศษจะดำเนินการและการอ้างอิงไปยังพารามิเตอร์จะถูกคัดลอกไปยังสแต็ก แต่ไม่มีมาโครที่เกี่ยวข้อง

หากรหัสพิเศษเป็นปัญหาคุณสามารถใช้การประกาศนี้แทน:

(decltype(Unreferenced(bar1, bar2)))0;

แต่ ณ จุดนั้นมาโครสามารถอ่านได้ง่ายขึ้น:

#define UNREFERENCED(...) { (decltype(Unreferenced(__VA_ARGS__)))0; }

1

ใช้งานได้ดี แต่ต้องใช้C ++ 11

template <typename ...Args>
void unused(Args&& ...args)
{
  (void)(sizeof...(args));
}

1
สิ่งนี้ต้องใช้ C ++ 14 และจะไม่ทำงานใน C ++ 11 ฉันไม่เห็นอะไรเลย นอกจากนี้ยังไม่แนะนำให้ใช้ALLCAPSกับสิ่งใดนอกจากแมโครซึ่งจะทำให้ดูน่าเกลียดและไม่พึงประสงค์ แต่ไม่มีอะไรที่ไม่ดีเกี่ยวกับเรื่องนี้จริงๆยกเว้นว่า a static_castจะดีกว่า
underscore_d

0

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

แมโครอื่นจำเป็นต้องระงับการเตือนตัวแปรโกลบอลแบบคงที่ที่ไม่ได้ใช้

template <typename T>
const T* UNUSED_VARIABLE(const T& dummy) { 
    return &dummy;
}
#define UNUSED_GLOBAL_VARIABLE(x) namespace {\
    const auto dummy = UNUSED_VARIABLE(x);\
}

static int a = 0;
UNUSED_GLOBAL_VARIABLE(a);

int main ()
{
    int b = 3;
    UNUSED_VARIABLE(b);
    return 0;
}

ใช้งานได้เนื่องจากไม่มีการเตือนสำหรับตัวแปรโกลบอลที่ไม่คงที่ในเนมสเปซที่ไม่ระบุชื่อ

ต้องใช้ C ++ 11

 g++  -Wall -O3  -std=c++11 test.cpp

0

ฮ่า ๆ! ฉันไม่คิดว่าจะมีคำถามอีกข้อใน SO ที่เปิดเผยคนนอกศาสนาที่ได้รับความเสียหายจากความโกลาหลที่ดีกว่านี้!

ด้วยความเคารพจากทุก C ++ 17 มีแนวทางที่ชัดเจนในc ++ แนวทางหลัก AFAIR ย้อนกลับไปในปี 2009 ตัวเลือกนี้มีให้ใช้เช่นเดียวกับวันนี้ และถ้าใครบางคนบอกว่ามันถือเป็นข้อผิดพลาดใน Doxygen ก็มีข้อผิดพลาดใน Doxygen


-14

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

คำเตือนถูกต้องไม่จำเป็นต้องปิด ไม่ได้ทำให้โปรแกรมใช้ไม่ได้ - แต่ควรมีเอกสารว่ามีเหตุผล


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

4
ในโครงการที่ฉันทำงานเมื่อปีที่แล้วฉันเปิดระดับการเตือนสูงสุดและได้รับการเตือน 10,000 ครั้ง เพียงไม่กี่โหลก็มีประโยชน์จริง ๆ ในบรรดาคนเหล่านั้นถูกซ่อนอยู่ประมาณหนึ่งโหลที่น่ารังเกียจจริงๆแมลง แต่มันต้องใช้เวลาหลายสัปดาห์ในการทำความสะอาดฐานรหัสจนถึงจุดที่เราจะได้เห็นคนที่จริงจังไม่กี่คน หากระดับการเตือนเพิ่มขึ้นตลอดเวลาและฐานรหัสถูกเก็บไว้โดยไม่มีการเตือนข้อผิดพลาดเหล่านั้นจะไม่พุ่งเข้าไปในรหัส
sbi

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

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

2
@sbi: การพูดคำหยาบในระดับคำเตือนสูงสุดสำหรับคอมไพเลอร์ของคุณคือรูปแบบของการวิเคราะห์โค้ดแบบคงที่ การวิเคราะห์โค้ดแบบสแตติกเป็นเพียงการอ่านโค้ดโดยไม่ต้องดำเนินการและหักข้อมูลออกจากมัน นั่นคือสิ่งที่คอมไพเลอร์ทำเมื่อเขาตรวจสอบกฎสำหรับคำเตือน
Tobias Langner
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.