Kompilator zrobi dokładnie to co chcesz. DOKŁADNIE!

i właśnie dlatego trzeba uważać. Ta zagadka jak i pozostałe ma na celu zwrócenie uwagi na miejsca które wydają się oczywiste a moga wprowadzić wiele zamieszania i niepotrzebnych nerwów. W końcu nie od dziś wiadomo że najgroźniejsze błędy znajdują się w „kodzie który napewno jest dobrze”. Tym razem zagadka wymaga trochę więcej od czytelnika, nie wystarczy znajmość C++, trzeba się jeszcze wykazać odrobiną znajomości biblioteki boost.
Na problem oczywiście musiałem trafić na klika godzin przed oddaniem projektu, była godzina 5:14 i nie trudno zgadnąć że odchodził istny eXtreme programming – programowanie gry sieciowej – 2 osoby – 24h. Dojście do tego co jest źle zajęło dobrą godzinę…
Poniższy kod przdstawia 4 najprostsze możliwe przypadki użycia boost::bind w połączeniu z boost::signal, nie różnią się między sobą bardzo:

#include <boost/signal.hpp>
#include <boost/bind.hpp>

#include <iostream>	

class Test
{
public:
  Test(int x) : x_(x)
  {}

  void metoda1(int i);

  int x_;
};

void Test::metoda1(int i)
{
  x_ += i;
}

int main()
{
  typedef boost::signal<void (int)> event_sig;
  event_sig signal;

  Test* t1 = new Test(0);
  Test* t2 = new Test(0);
  Test t3(0);
  Test t4(0);

  signal.connect(boost::bind(&Test::metoda1, *t1, _1));
  signal.connect(boost::bind(&Test::metoda1,  t2, _1));
  signal.connect(boost::bind(&Test::metoda1, &t3, _1));
  signal.connect(boost::bind(&Test::metoda1,  t4, _1));

  for(int i = 0; i < 10; ++i)
  {
    signal(1);
  }

  std::cout << "t1::x = " << t1->x_ << std::endl;
  std::cout << "t2::x = " << t2->x_ << std::endl;
  std::cout << "t3::x = " << t3.x_ << std::endl;
  std::cout << "t4::x = " << t4.x_ << std::endl;
  std::cout << "Powinno(?) byc 10" << std::endl;
}

Mogło by się wydawać że w wyniku, na ekran zostanie wypisana 4 razy liczba 10. Ci bardziej podejrzliwi zaczną się zastanawiać, jaki wpływ mogą mieć te „dodatkowe” symbole dostawione wewnątrz boost::bind. Okazuje się że w przypadkach 1 i 4 ( t1 i t4 ), mimo wysyłania sygnału, wartość pola x_ nie ulega zmianie, natomiast w pozostałych ulega. Dlaczego ?
Rozwiązanie tego problemu jest bardo proste, otóż tworząc binda, biblioteka boost w zależności od sposobu przekazania obiektu na rzecz którego zostanie wywołana metoda, utworzy jego kopię (internal copy) lub będzie operować na przekazanym obiekcie.
Niby proste, ale trzeba mieć świadomość o istnieniu takiego mechanizmu. Nie trudno się „przejechać” na złym przekazaniu obiektu, a tu nie będzie sugestywnego „segmentation fault”….