我正在开发一个用VC9构建的应用程序,我遇到了一个我不完全理解的警告:为什么在构造函数的右括号上有一个“无法访问的代码”警告?
重现问题的最小测试用例是:
__declspec(noreturn) void foo() { // Do something,then terminate the program } struct A { A() { foo(); } // d:\foo.cpp(7) : warning C4702: unreachable code }; int main() { A a; }
必须使用/ W4编译才能触发警告.或者,您可以使用/ we4702编译以强制检测此警告时出错.
d:\>cl /c /W4 foo.cpp Microsoft (R) C/C++ Optimizing Compiler Version 15.00.21022.08 for x64 Copyright (C) Microsoft Corporation. All rights reserved. foo.cpp d:\foo.cpp(7) : warning C4702: unreachable code
有人可以解释一下,究竟是什么在这里无法到达?我最好的理论是它是析构函数,但我想要一个确定的答案.
如果我想让这段代码警告清洁,我该如何实现呢?我能想到的最好的是将其转换为编译时错误.
struct A { private: A(); // No,you can't construct this! }; int main() { A a; }
编辑:为了澄清,使用noreturn函数终止程序通常不会在封闭该函数调用的右括号上导致无法访问的代码警告.
__declspec(noreturn) void foo() { // Do something,then terminate the program } struct A { A() { } ~A() { foo(); } }; int main() { A a; }
结果是:
d:\>cl /c /W4 foo3.cpp Microsoft (R) C/C++ Optimizing Compiler Version 15.00.21022.08 for x64 Copyright (C) Microsoft Corporation. All rights reserved. foo3.cpp
解决方法
Gorpik走在正确的轨道上.我创建了两个类似的测试用例,编译它们并对它们进行反汇编,我想我已经理解了它的根本原因:构造函数总是隐式生成一个return语句,并且由于noreturn函数,这个return语句是无法访问的.
noreturn_constructor.cpp
__declspec(noreturn) void foo() { // Do something,then terminate the program } struct A { A() { foo(); } ~A() { } }; int main() { A a; }
noreturn_destructor.cpp
__declspec(noreturn) void foo() { // Do something,then terminate the program } struct A { A() { } ~A() { foo(); } }; int main() { A a; }
diff -u * .disasm
--- noreturn_constructor.disasm 2012-05-30 11:15:02.000000000 -0400 +++ noreturn_destructor.disasm 2012-05-30 11:15:08.000000000 -0400 @@ -2,7 +2,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. -Dump of file noreturn_constructor.obj +Dump of file noreturn_destructor.obj File Type: COFF OBJECT @@ -35,15 +35,15 @@ ??0A@@QEAA@XZ (public: __cdecl A::A(void)): 0000000000000000: 48 89 4C 24 08 mov qword ptr [rsp+8],rcx - 0000000000000005: 48 83 EC 28 sub rsp,28h - 0000000000000009: E8 00 00 00 00 call ?foo@@YAXXZ - 000000000000000E: 48 8B 44 24 30 mov rax,qword ptr [rsp+30h] - 0000000000000013: 48 83 C4 28 add rsp,28h - 0000000000000017: C3 ret + 0000000000000005: 48 8B 44 24 08 mov rax,qword ptr [rsp+8] + 000000000000000A: C3 ret ??1A@@QEAA@XZ (public: __cdecl A::~A(void)): 0000000000000000: 48 89 4C 24 08 mov qword ptr [rsp+8],rcx - 0000000000000005: C3 ret + 0000000000000005: 48 83 EC 28 sub rsp,28h + 0000000000000009: E8 00 00 00 00 call ?foo@@YAXXZ + 000000000000000E: 48 83 C4 28 add rsp,28h + 0000000000000012: C3 ret Summary
无法访问的代码是这个隐式的return语句,它是在构造函数中生成的,而不是析构函数:
- 000000000000000E: 48 8B 44 24 30 mov rax,qword ptr [rsp+30h] + 0000000000000005: 48 8B 44 24 08 mov rax,qword ptr [rsp+8]