G ++编译错误的STL代码

时间:2012-01-10 15:33:45

标签: stl g++

我想我发现了一个G ++错误,但我不确定。我无法解释。编译不应该传递BAD代码,但确实如此。 g ++ - 4.5和g ++ 4.6 -std = c ++ 0x在没有任何警告的情况下传递此代码。

因为编译认为指向Bar对象的指针是Bar对象本身。 我疯了。我花了很多时间才得到这个bug。有没有什么技术可以防止这种错误?

错误代码:

 g++-4.6 for_stackoverflow.cpp && ./a.out
 address of bar in main()   0xbff18fc0
 Foo 0x9e80008      Bar     0xbff18fec
 Foo 0x9e80028      Bar     0xbff18fec
 Foo 0x9e80048      Bar     0xbff18fec
 end

源代码:

     #include <iostream>
     #include <list>
     #include <iomanip>
     #include <algorithm>

     #define BAD

     using namespace std;

     class Bar;

     class Foo {
     public:
       virtual void tick(Bar & b) {
         cout << "Foo " << this << "      Bar " << setw(14) << (&b) << endl;
       }    
     };

     class Bar : public list<Foo*> {
     };

     int main() {
       Bar bar;
       cout << "address of bar in main()   " << &bar << endl;
       bar.push_back(new Foo());
       bar.push_back(new Foo());
       bar.push_back(new Foo());
     #ifdef GOOD
       for_each(bar.begin(), bar.end(), bind2nd(mem_fun(&Foo::tick), bar));
     #elif defined(BAD)
       for_each(bar.begin(), bar.end(), bind2nd(mem_fun(&Foo::tick), &bar));
     #else
     #error "define GOOD xor BAD"
     #endif
       cout << "end" << endl;
       return 0;
     }

1 个答案:

答案 0 :(得分:0)

bind2nd声明为:

template <class Fn, class T>
binder2nd<Fn> bind2nd(const Fn&, const T&);

这意味着推断出T类型,在本例中为Bar *

在我的系统上,它实现为:

template<typename _Operation, typename _Tp>
inline binder2nd<_Operation>
bind2nd(const _Operation& __fn, const _Tp& __x)
{
  typedef typename _Operation::second_argument_type _Arg2_type;
  return binder2nd<_Operation>(__fn, _Arg2_type(__x));
} 

要了解为什么会编译考虑:

class Bar {};

int main() {
  Bar *b = 0;
  typedef const Bar& type;
  const type t = type(b);
}

这似乎是真正的问题,并且使用g ++进行编译,因为it's basically a reinterpret_cast

最简单的解决方法是将其更改为使用boost::bind(或std::bind用于C ++ 11):

#include <boost/bind.hpp>

...

boost::bind(mem_fun(&Foo::tick), _1, &bar)

或lambda函数 会给出您希望看到的错误。