未使用的参数在C + + 11
在c + + 03和更早版本中,禁用关于未使用参数的编译器警告,我通常使用这样的代码:
#define UNUSED(expr) do { (void)(expr); } while (0)
例如
int main(int argc, char *argv[]) { UNUSED(argc); UNUSED(argv); return 0; }
但是对于c ++来说,macros并不是最佳实践,所以。 有没有更好的解决scheme出现在C ++ 11标准? 我的意思是我可以摆脱macros吗?
感谢所有!
为了这个目的,我使用了一个空的函数:
template <typename T> void ignore(T &&) { } void f(int a, int b) { ignore(a); ignore(b); return; }
我希望任何严肃的编译器能够优化函数调用,并为我保持警告。
您可以省略参数名称:
int main(int, char *[]) { return 0; }
而在main的情况下,你甚至可以完全省略参数:
int main() { // no return implies return 0; }
请参阅C ++ 11标准中的“3.6开始和终止”。
没有什么等价物,不。
所以你坚持使用旧的选项。 您是否乐意完全忽略参数列表中的名称?
int main(int, char**)
在main
的特定情况下,当然,您可以简单地省略这些参数:
int main()
还有一些典型的特定于实现的技巧,比如GCC的__attribute__((unused))
。
在C ++ 11中有<tuple>
,其中包括准备使用std::ignore
对象,这允许我们写(很可能不会增加运行开销):
void f(int x) { std::ignore = x; }
要“禁用”这个警告,最好避免写入参数,只写types。
void function( int, int ) { }
或者如果您愿意的话,请注明:
void function( int /*a*/, int /*b*/ ) { }
您可以混合命名和未命名的参数:
void function( int a, int /*b*/ ) { }
macros可能不是理想的,但是他们为了这个特定的目的做了很好的工作。 我会说坚持使用macros。
你有什么反对旧的和标准的方式?
void f(int a, int b) { (void)a; (void)b; return; }
没有新的东西可用。
最适合我的是在实现中注释掉参数名称。 这样,你摆脱了警告,但仍然保留一些什么参数(因为名称是可用的)的概念。
你的macros(以及其他每一个cast-to-void方法)都有一个缺点,就是你可以在使用macros之后真正使用这个参数。 这可能会使代码难以维护。
Boost头文件<boost/core/ignore_unused.hpp>
(Boost> = 1.56)为此目的定义了函数模板boost::ignore_unused()
。
int fun(int foo, int bar) { boost::ignore_unused(bar); #ifdef ENABLE_DEBUG_OUTPUT if (foo < bar) std::cerr << "warning! foo < bar"; #endif return foo + 2; }
PS C ++ 17 似乎获得 [[maybe_unused]]
属性来提供一个标准的方式来声明一个未使用的variables。
windows.h定义了UNREFERENCED_PARAMETER :
#define UNREFERENCED_PARAMETER(P) {(P) = (P);}
所以你可以这样做:
#include <windows.h> #include <stdio.h> int main(int argc, char **argv) { UNREFERENCED_PARAMETER(argc); puts(argv[1]); return 0; }
或在Windows之外:
#include <stdio.h> #define UNREFERENCED_PARAMETER(P) {(P) = (P);} int main(int argc, char **argv) { UNREFERENCED_PARAMETER(argc); puts(argv[1]); return 0; }
我真的很喜欢使用macros,因为它允许你有更好的控制,当你有不同的debugging版本(例如,如果你想build立与断言启用):
#if defined(ENABLE_ASSERTS) #define MY_ASSERT(x) assert(x) #else #define MY_ASSERT(x) #end #define MY_UNUSED(x) #if defined(ENABLE_ASSERTS) #define MY_USED_FOR_ASSERTS(x) x #else #define MY_USED_FOR_ASSERTS(x) MY_UNUSED(x) #end
然后像这样使用它:
int myFunc(int myInt, float MY_USED_FOR_ASSERTS(myFloat), char MY_UNUSED(myChar)) { MY_ASSERT(myChar < 12.0f); return myInt; }
我有自己的实现时间关键的代码段。 我一直在研究一段时间关键的代码来减慢速度,并且发现这个实现从我已经优化的时间关键代码中消耗了大约2%
#define UTILITY_UNUSED(exp) (void)(exp) #define UTILITY_UNUSED2(e0, e1) UTILITY_UNUSED(e0); UTILITY_UNUSED(e1) #define ASSERT_EQ(v1, v2) { UTILITY_UNUSED2(v1, v2); } (void)0
时间关键的代码已经使用了ASSERT*
定义来进行debugging,但是在发行版中显然已经被切断了,但是…看起来这个在Visual Studio 2015 Update 3
产生了一些更快的代码:
#define UTILITY_UNUSED(exp) (void)(false ? (false ? ((void)(exp)) : (void)0) : (void)0) #define UTILITY_UNUSED2(e0, e1) (void)(false ? (false ? ((void)(e0), (void)(e1)) : (void)0) : (void)0)
原因是双false ?
expression。 它以某种方式产生一个更快的代码在释放与最大限度的优化。
我不知道为什么这是更快的(似乎是编译器优化中的一个错误),但它至less是一个更好的解决scheme,这种情况下的代码。
注意 :这里最重要的是时间关键的代码在发布时没有上述断言或者未使用的macros的情况下变慢。 换句话说,双重false ?
expression式令人惊讶地有助于优化代码。