代码之家  ›  专栏  ›  技术社区  ›  sharptooth

一个“变量名”C++语句是否始终是一个“否”?

  •  20
  • sharptooth  · 技术社区  · 13 年前

    COM_INTERFACE_ENTRY_FUNC_BLIND ATL宏:

    HRESULT WINAPI blindQuery( void* /*currentObject*/, REFIID iid, void** ppv, DWORD_PTR /*param*/ ) 
    {
        DEBUG_LOG( __FUNCTION__ ); //DEBUG_LOG macro expands to an empty string in non-debug
        DEBUG_LOG( iid );
        iid; // <<<<<<<----silence compiler warning
        if( ppv == 0 ) {
            return E_POINTER;
        }
        *ppv = 0;
        return E_NOINTERFACE;
    }
    

    在上面的例子中 iid DEBUG_LOG 在非调试配置中展开为空字符串的宏。所以评论或删除 签名中的变量名不是选项。编译非调试配置时,编译器生成 C4100: 'iid' : unreferenced formal parameter iid; 增加了被认为是禁止操作的语句。

    问题是:如果我们有以下任何声明:

     CSomeType variableName; //or
     CSomeType& variableName; //or
     CSomeType* variableName;
    

    将在C++代码中声明以下语句:

    variableName;
    

    在任何时候都不要做任何事 CSomeType 是?

    2 回复  |  直到 13 年前
        1
  •  47
  •   Community Egal    7 年前

    是的,但你可能会收到另一个警告。

    这样做的标准方法是: (void)iid;


    从技术上讲,这仍然可以加载 iid volatile 变量。

    完全地

    也就是说,我们现在拥有的是:

    #define USE(x) (void)(x)
    
    // use iid in an expression to get rid of warning, but have no observable effect
    USE(iid); 
    
    // hm, result of expression is gone but expression is still evaluated
    USE(std::cout << "hmmm" << std::endl);
    

    这接近于一个解决方案:

    // sizeof doesn't evaluate the expression
    #define USE(x) (void)(sizeof(x))
    

    但失败的原因是:

    void foo();
    
    // oops, cannot take sizeof void
    USE(foo());
    

    解决办法是简单地:

    // use expression as sub-expression,
    // then make type of full expression int, discard result
    #define USE(x) (void)(sizeof((x), 0))
    

    这保证了没有任何操作。

    编辑: 上面确实保证没有效果,但我没有测试就发布了。在测试时,它会再次生成警告,至少在MSVC 2010中是这样,因为 价值


    提醒:我们想“使用”一个表达式,而不是对它进行求值。怎么能做到?这样地:

    #define USE(x) ((void)(true ? 0 : (x)))
    

    这有一个简单的问题,就像上次一样(实际上更糟),就是 (x) int . 这又是一个微不足道的问题:

    #define USE(x) ((void)(true ? 0 : ((x), 0)))
    

    我们又回到了上次的效果(没有),但这次 x

    这个解决方案实际上还有一个问题(在上一个联合国解决方案中也存在,但没有被注意到),在这个例子中出现了这个问题:

    struct foo {};
    void operator,(const foo&, int) {}
    
    foo f;
    USE(f); // oops, void isn't convertible to int!
    

    (十) 将逗号运算符重载为不可转换为 内景

    #define USE(x) ((void)(true ? 0 : ((x), void(), 0)))
    

    以确保我们真的以零结束。 This trick brought to you by Johannes .


    另外,如前所述,如果以上还不够,一个足够愚蠢的编译器可能会潜在地“加载”表达式 0 (在登记簿上或其他地方),然后忽略它。

        2
  •  2
  •   Peter Alexander    13 年前

    好吧,不看编译器的源代码是不可能百分之百确定的,但是如果这能在现代编译器中生成任何代码,我会非常惊讶。

    最后,如果您担心任何特定的实例,那么您可以随时查看生成的程序集代码。