我想我发现了一个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;
}
答案 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函数 会给出您希望看到的错误。