【问题标题】:C++: How to trigger a compiler error when function return value is unused?C ++:未使用函数返回值时如何触发编译器错误?
【发布时间】:2011-08-13 19:14:45
【问题描述】:

假设我有一个标准化函数定义为:

Vec3f Vec3f::getNormalized() const {
   return (*this)/this->length();
}

如果使用此函数而没有存储它的返回值,是否有可能以某种方式创建编译时错误? ;

v.getNormalized(); // which most definitely is a typo

..而不是..

v = v.getNormalized(); 

【问题讨论】:

  • 如果方法被声明为const 并且没有存储返回值,我认为这个问题会被优化掉,所以你不必担心。但无论如何,这是个好问题。
  • 从优化的角度来看,我认为这不是问题,不管函数是否声明为 const。
  • 可以吗,如果你可以在运行时检查它?
  • 我不知道这是否只是为了举例,但如果不是,你能避免“v = v.blah()”或“v = blah(v)”,如果可能的话使用计算的每个阶段都有不同的变量,即使没有编译器检查,当您遗漏分配时也会让您更加明显? “Vec3f v_init = foo(); v_norm = v.GetNormalised(); Vec3f v_ans = v_norm * v_other; 等等;”
  • 或者,不是你真正想要的,而是使用二元函数或运算符,所以“v.assignNormalisedTo(v)”。

标签: c++ compiler-errors return-value


【解决方案1】:

在 GCC 中,使用 -Wunused-result 在忽略函数的返回值时触发警告。如果您想要错误而不是警告,请使用-Werror 将所有警告转换为错误。如需更多信息,请参阅 GCC Warning Options

似乎没有针对 Visual C++ 编译器的等效警告。 (如果我错了,请使用 Visual C++ 信息编辑此回复。)

【讨论】:

    【解决方案2】:

    没有办法知道返回值是否被取走。保证传入的唯一方法是通过引用传入返回值。

    【讨论】:

    • 换句话说,void Vec3f::getNormalized(Vec3f& result) 但是要小心如果你调用v.getNormalised(v)会发生什么
    • 彼得赫尔;在这种情况下,我会将函数设为静态。
    【解决方案3】:

    我认为这在编译时是不可能的,除非使用编译器标志 @Ashwin noted

    但是,如果可以在运行时生成错误,您也许可以使用一些技巧,例如使用代理类:

    template <typename T>
    struct Return
    {
        Return(const T & value) 
          : value_(value), used_(false) 
        {}
    
        Return(const Return & other) 
          : value_(other.value_), used_(false) 
        { 
            other.used_ = true; 
        }
    
    
        Return & operator=(const Return & other)
        {
            other.used_ = true;
            value_ = other.value;
            return *this;
        }
    
        operator T() const 
        { 
            used_ = true; 
            return value_;
        }
    
        ~Return() // generates an error if the value hasn't been used
        { 
            assert(used_); 
        }
    
      private:
    
        T value_;
        mutable bool used_;
    };
    
    Return<int> foo()
    {
        return 42;
    }
    
    int main()
    {
        int i = foo();                   // ok
        std::cout << foo() << std::endl; // ok
    
        foo();                           // assertion failed
    }
    

    您只需更改函数的返回类型,使其返回Return&lt;Vec3f&gt;,如果函数的结果未使用,您应该会收到错误消息。但是,我不确定我是否会建议这样做,因为它会使代码变得不那么清晰,并且也可能被滥用。只要您的功能有据可查,您就应该对您的用户充满信心:)!

    【讨论】:

    • 我正在考虑类似的事情。我不会在实际代码中使用它,但它是一个不错的学术解决方案。
    【解决方案4】:

    使用 clang,您可以有选择地将给定的警告转换为错误(而不是全部)。

    这是通过-Werror=foo 实现的,其中foo 是警告的名称。在这里,我认为-Werror=unused-expr 是您所需要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-11
      • 2011-12-13
      • 1970-01-01
      • 1970-01-01
      • 2017-09-08
      • 2014-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多