有没有一种好方法可以确保不忽略C ++函数结果?

时间:2011-06-21 23:48:47

标签: c++ lint

我最近遇到一个案例,我有一个const成员函数执行一个操作并返回一个结果。例如,

class Foo { ...
    Foo add(Foo const & x) const;
}

但其他人无意中称它为更新this对象(忽略结果):

Foo a = ...;
Foo b = ...;
a.add(b);

(这个错误实际上是由一个不完美的重构引入的。)

有没有办法让上面的最后一行触发错误或警告?接下来最好的事情是运行时捕获,主要通过以下模板解决。但是,它会导致返回值优化,如计数器结果所示。

template<typename T>
class MustTake {
    T & obj;
    bool took;
public:
    MustTake(T o) : obj(o), took(false) {}
    ~MustTake() { if (!took) throw "not taken"; }
    operator T&() { took = true; return obj;}
};

struct Counter {
    int n;
    Counter() : n(0) {}
    Counter(Counter const & c) : n(c.n+1) {}
    ~Counter() {}
};

Counter zero1() {
    return Counter();
}

MustTake<Counter> zero2() {
    return Counter();
}

int main() {
    Counter c1 = zero1();
    printf("%d\n",c1.n);    // prints 0
    Counter c2 = zero2();
    printf("%d\n",c2.n);    // prints 1
    zero1();    // result ignored
    zero2();    // throws
    return 0;
}

我想我可以通过使用宏来改善低效率,以便MustTake&lt;&gt;是仅调试和无操作版本。

我正在寻找编译时解决方案。如果做不到这一点,我正在寻找最佳的运行时解决方案。

3 个答案:

答案 0 :(得分:8)

这是GCC和Clang中(documentation)的函数属性,但它不可移植到例如MSVC。

class Foo { ...
    __attribute__((warn_unused_result))
    Foo add(Foo const & x) const;
}

文档说明它已在realloc 上使用,例如,但它不会出现在我系统上的任何其他标准函数中。

您可能还有兴趣使用Clang静态分析器,它可以跟踪函数调用中的数据流,并且可以为您提供更好的警告。

答案 1 :(得分:7)

对于Microsoft VC ++,有_Check_return_注释:http://msdn.microsoft.com/en-us/library/ms235402(v=VS.100).aspx

答案 2 :(得分:0)

如果函数调用者不能忽略返回值很重要,则可以按如下方式使用模板dont_ignore

在:

int add( int x, int y )
{
    return x + y;
}

在:

dont_ignore<int> add( int x, int y )
{
    return x + y;
}

当函数的调用者不使用返回值时,抛出异常。 dont_ignore的定义:

template<class T>
struct dont_ignore
{
    const T     v;
    bool        used;

    dont_ignore( const T& v )
        :  v( v ), used( false )
    {}

    ~dont_ignore()
    {
        if ( !used )
            throw std::runtime_error( "return value not used" );
    }

    operator T()
    {
        used = true;
        return v;
    }
};