不要作温水里的那只青蛙

来源:互联网 发布:linux 网站 编辑:程序博客网 时间:2024/04/28 09:50
问题的起因很简单,我实验一个简单的程序不过。这个程序的本意是想检验一下 boost.bind 在 1.33 中新加入的比较运算符,我以为这一点也不难,然而程序的运行结果大出我的意料:

#include
#include
#include
#include

//#include
//#include
#include

//using namespace boost::lambda;
using namespace boost;

class Person
{
public:
  Person(){}
  Person(const std::string& name) : name_(name){}

  std::string& Name()
  { return name_; }

private:
  std::string name_;

};

int main()
{
  std::map persons;
  persons[123] = Person("Amy");
  persons[234] = Person("Ralph");
  persons[345] = Person("Simon");
  persons[456] = Person("Maggie");

  std::cout << "Ralph's Id is: " <<
    std::find_if( persons.begin(), persons.end(),
      bind(&Person::Name,
        bind(&std::map::value_type::second, _1)) ==
"Ralph" )->first;
}

它的输出竟然是

Ralph's Id is: 0

不过,如果把程序中的 bind 库换成 boost.lambda (uncomment 掉前面的 include 和 using 即可),输出就是

Ralph's Id is: 234

这才是我想要的,我在新闻组提了这个问题,Peter Dimov 给我的答复可能是对我们每个使用 boost.bind 的人的忠告:

I get an error C2439 on this example; the problem is that the inner
bind returns a temporary Person by value, but Person::Name returns a
reference to its member std::string.

bind on a data member was changed to return a value and not a reference
because of similar reference to temporary issues, but it seems clear
now that this change has caused more problems than it solved.

I'll try to fix it for the next release (1.33.1 if there is one, or
1.34), but in the meantime you need to use

bind(&std::map::value_type::second, _1)

to get the old reference-returning behavior back.

区别在于 bind 这一部分,现在我们将不得不显式的指出我们绑定到一个 data member 的目的是取得它的 reference 而不是一份拷贝。在修改这个问题之前,一定要小心处理这个问题,否则就会跟我一样目瞪口呆。






原创粉丝点击