将指针传递给期望引用的函数会更改指向的值

时间:2017-09-07 17:21:11

标签: c++ pointers boost bind

我有以下代码示例。我正在将指针传递给函数。当我将指针传递给函数时,函数似乎将参数初始化为某个随机数。但是,当我将变量的地址传递给函数时,它会给出预期的结果。

// find_if example
#include <iostream>     // std::cout
#include <algorithm>    // std::find_if
#include <vector>       // std::vector

class A 
{
public:

A(int i) { num = i; }

bool IsPresent (A& a) {
  std::cout << "Comparing " << num << " vs " << a.num << '\n';
  return (num == a.num);
};

int num;
};

int main () {
  std::vector<A*> myvector;

  A a1(10);
  A a2(20);
  A a3(30);
  A a4(40);

  A a(40);
  const A *pa = &a;

  std::cout << "pa is " << pa << '\n';

  myvector.push_back(&a1);
  myvector.push_back(&a2);
  myvector.push_back(&a3);
  myvector.push_back(&a4);

  std::vector<A*>::iterator it = std::find_if (myvector.begin(), myvector.end(), 
                                                                  std::bind2nd(std::mem_fun(&A::IsPresent), pa));
  if (it != myvector.end())
      std::cout << "The first equal value is " << (*it)->num << '\n';
  else
      std::cout << "Cannot find a match";

  return 0;
}
  1. 为什么函数bool IsPresent (A& a)在指针传递参数时将变量(A& a)初始化为随机值,并在我传递参数时起作用?
  2. 作为指针传递时,结果为

    pa is 0x7b10b4d52e80
    Comparing 10 vs -1261097344
    Comparing 20 vs -1261097344
    Comparing 30 vs -1261097344
    Comparing 40 vs -1261097344
    Cannot find a match
    

    当作为参考传递时:

    pa is 0x75002e9dbb30
    Comparing 10 vs 40
    Comparing 20 vs 40
    Comparing 30 vs 40
    Comparing 40 vs 40
    The first equal value is 40
    
    1. 为什么代码首先编译?我调用的函数需要一个引用,我传递一个指针。如果找不到函数,编译器是否应该发出警告/错误?

2 个答案:

答案 0 :(得分:2)

std::bind2nd is really poorly designed.

template< class F, class T >
std::binder2nd<F> bind2nd( const F& f, const T& x )

评估为:

std::binder2nd<F>(f, typename F::second_argument_type(x))

是的,那是一个C风格的演员。

我们最终会执行(A&)(pa),即reinterpret_cast<A&>(pa)

A指针的内存重新解释为A的实例。

我是否说bind2nd设计不合理?我的意思是。

C ++ 11带来了lambdas和std::bind,它们都是头肩,身体和脚,基础和行星在bind2ndbind1st之上。

有一个原因导致std::bind2nd被弃用并从标准中移除。这只是部分的原因(也因为它依赖于它的函数参数来告诉它参数类型是什么,std::bind没有)。

std::mem_fun也已弃用并已从标准中删除,但此处没有任何错误。尽管如此,将其替换为std::mem_fn,它可以完成同样的工作,但作为第一步更好。

如果std::mem_fun盲目地将std::mem_fn替换为std::bind2ndstd::bind( first_arg, std::_1, second_arg )替换second_arg,除非std::vector<A*>::iterator it = std::find_if ( myvector.begin(), myvector.end(), [pa](A* a){ a->IsPresent(*pa); } ); 与正确的类型匹配,否则您的代码将无法编译。它会在一堆模板垃圾邮件中这样做。

更好的是:

pa

如果您忘记取消引用a,则会生成一个非常简单且易于阅读的编译器错误消息。

答案 1 :(得分:0)

为什么函数bool IsPresent(A&amp; a)在指针传递参数时将变量(A&amp; a)初始化为随机值,并在我传递参数时起作用?

“A&amp; a”参数被定义为引用变量,当您传递指针对象时,它会尝试将对象解释为引用。正确的方法是传递其内容。

为了改善您的解决方案,您可以将isPresent定义为bool isPresent(const A&amp; a)

为什么代码首先编译?我调用的函数需要一个引用,我传递一个指针。如果找不到函数,编译器是否应该发出警告/错误?

它可以被错误地解释为参考。因此,它可以正确编译,但执行失败。