我有一个宏定义如下:
#define UNREF_PARAM_1(a)
do { \
(void)sizeof(a); \
} \
while (0)
为了消除编译器警告。在我正在进行的新项目中,VS2013突然再次抱怨未引用的形式参数。
奇怪的是,如果我只使用
(void)param
,它确实可以工作。有人知道为什么使用 (void)sizeof(param)
时不起作用吗?我有一个宏定义如下:
#define UNREF_PARAM_1(a)
do { \
(void)sizeof(a); \
} \
while (0)
(void)param
,它确实可以工作。有人知道为什么使用 (void)sizeof(param)
时不起作用吗?sizeof(param)
中,param
是所谓的未求值操作数,因此不是odr-used -也就是说,在运行时不需要它。然而,(void)param
确实构成了odr-use。使用您代码中的符号表示法进行转换在内部调用static_cast
。[expr.static.cast]/6:
[p.expr]/10:任何表达式都可以显式转换为类型cv
void
,在这种情况下,它变成了一个弃值表达式(Clause 5)。
[basic.def.odr]/2:在某些上下文中,一个表达式只出现为了它的副作用。这样的表达式称为被弃值的表达式。表达式被评估并且其值被丢弃。[…] lvalue-to-rvalue转换(4.1)仅在表达式是易失性限定类型的lvalue时应用[…]
这个引用的第一部分指定除非它是未求值操作数(Clause 5)或其子表达式,否则表达式是可能被评估的。表达式的名称作为可能被评估的表达式出现的变量被odr-used,除非它是一个满足出现在常量表达式中的要求(5.19)且立即应用了lvalue-to-rvalue转换(4.1)的对象。
sizeof(a)
不是a
的odr-use,因为a
是未求值操作数。显然,(void)a
被可能评估。因为a
肯定不允许出现在常量表达式中,也没有声明为volatile
,所以不会立即应用lvalue-to-rvalue转换,因此a
是odr-used。typeid(x)
,其中x
不是多态类类型的glvaluesizeof(x)
(和sizeof x
)noexcept(x)
decltype(x)
alignof(x)
? alignas(x)
?
sizeof
在编译时被求值。 - Ed S.