2

Given the following test code

#include <iostream>
#include <tr1/functional>
using namespace std;

struct cl { 
  cl(){ cout << "  cl()\n"; } 
  cl(const cl& from){ cout << "  cl()[copy]\n"; } 
  ~cl(){ cout << "  ~cl()\n";}
};
void  f1(const cl& data){}
void  f2(const cl* pData){}

int main(int c, char** a)
{
  cout << "enter:\n";
  cl data;
  cout << "ref:\n";
  tr1::bind(&f1, data);
  cout << "ptr:\n";
  tr1::bind(&f2, &data);
  cout << "exit:\n";
  return 0;
}

I get the following output:

$ g++ tr1BindDtorTest.cpp && ./a.out
enter:
  cl()
ref:
  cl()[copy]
  cl()[copy]
  cl()[copy]
  ~cl()
  ~cl()
  ~cl()
ptr:
exit:
  ~cl()

When I create a binding involving references to my class/struct objects are created and destroyed multiple times.

Same exact test but with pointers there are no such objects

I can't see why the behaviour will be different between pass by value & reference, I always thought of reference as syntactic sugar for pointer, and so reasoned that the behaviours should be identical.

Anyone care to explain?

[g++ 4.4.6 linux & 4.2.1 on macos]

nhed
  • 5,774
  • 3
  • 30
  • 44

2 Answers2

6

Instead of this:

tr1::bind(&f1, data);

You need this:

tr1::bind(&f1, tr1::ref(data));

Boost has the same thing: boost::ref() must be used inside boost::bind() if you want the bound function object to store a reference to the data. Otherwise, the data will always be copied into the bound function object produced by bind().

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • +1 Thanks! why does it not complain if I use ref and not cref when the parameter is declared const? – nhed Feb 01 '14 at 12:41
  • Passing a non-const reference when a const one is required is perfectly fine. – John Zwinck Feb 01 '14 at 13:50
  • Can you elaborate on the fine-ness? Is it like a non const pointer to a const pointer? And if so why have both `ref()` and `cref()` – nhed Feb 01 '14 at 14:03
  • If you have a const object you cannot use ref() on it. But you can use cref(), and then you will be able to call const-by-ref methods. If you use cref() you will not be able to call non-const-by-ref methods. – John Zwinck Feb 02 '14 at 07:29
4

See cppreference documentation:

The arguments to bind are copied or moved, and are never passed by reference unless wrapped in std::ref or std::cref.