|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Here is the code which should compile fine; program output and my question
follows: __________________________________________________ __________________ #include <cstdio> namespace func_ptr { namespace sys { typedef void (callback_type) (void const* const); class base_pod { protected: callback_type* mp_callback; public: void execute() const { mp_callback(this); } }; template<typename T, typename T_mfptr, typename T_p1> class param_1 : public base_pod{ T m_obj; T_mfptr m_mfptr; T_p1 m_p1; public: param_1(T obj, T_mfptr mfptr, T_p1 p1) : m_obj(obj), m_mfptr(mfptr), m_p1(p1) { mp_callback = sys_callback; std::printf("(%p)-param_1::param_1()\n", reinterpret_cast<void*>(this)); } ~param_1() throw() { std::printf("(%p)-param_1::~param_1()\n", reinterpret_cast<void*>(this)); } private: void callback() const { (m_obj->*(m_mfptr))(m_p1); } static void sys_callback(void const* const state) { static_cast<param_1 const*>(state)->callback(); } }; } typedef sys::base_pod const& handle; template<typename T, typename T_mfptr, typename T_p1> sys::param_1<T, T_mfptr, T_p1> create(T _this, T_mfptr mfptr, T_p1 p1) { return sys::param_1<T, T_mfptr, T_p1>(_this, mfptr, p1); } } struct object { void func(int i) { std::printf("(%p)-object::func1(%d)\n", reinterpret_cast<void*>(this), i); } }; struct holder { func_ptr::handle m_fptr; holder(func_ptr::handle fptr) : m_fptr(fptr) {} }; int main() { object obj; { std::puts("Scope 1:\n"); func_ptr::handle h(func_ptr::create(&obj, &object::func, 123)); h.execute(); } std::puts("\n\n--------------------------------------------"); { std::puts("Scope 2:\n"); holder h(func_ptr::create(&obj, &object::func, 123)); h.m_fptr.execute(); } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~*/ std::puts("\n\n--------------------------------------------\n\ Press <ENTER> to exit..."); std::getchar(); return 0; } __________________________________________________ __________________ Here is the output I get: __________________________________________________ __________________ Scope 1: (0022FF30)-param_1::param_1() (0022FF5F)-object::func1(123) (0022FF30)-param_1::~param_1() -------------------------------------------- Scope 2: (0022FF30)-param_1::param_1() (0022FF30)-param_1::~param_1() (0022FF5F)-object::func1(123) -------------------------------------------- Press <ENTER> to exit... __________________________________________________ __________________ I am wondering why the const reference in 'Scope 2' (e.g., holder::m_fptr) is getting destructed _before_ the call to 'h.m_fptr.execute()'? I thought the output should be identical to that of 'Scope 1'... What exactly am I doing wrong here? I am screwing something up somewhere... What can be done to resolve this issue? Yikes! ;^(... Thanks. -- Chris M. Thomasson http://appcore.home.comcast.net |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
Chris Thomasson wrote:
> Here is the code which should compile fine; program output and my > question follows: > __________________________________________________ __________________ > #include <cstdio> > > > namespace func_ptr { > namespace sys { > typedef void (callback_type) (void const* const); > > class base_pod { > protected: > callback_type* mp_callback; > > public: > void execute() const { > mp_callback(this); > } > }; > > template<typename T, typename T_mfptr, typename T_p1> > class param_1 : public base_pod{ > T m_obj; > T_mfptr m_mfptr; > T_p1 m_p1; > > public: > param_1(T obj, T_mfptr mfptr, T_p1 p1) > : m_obj(obj), m_mfptr(mfptr), m_p1(p1) { > mp_callback = sys_callback; > std::printf("(%p)-param_1::param_1()\n", > reinterpret_cast<void*>(this)); > } > > ~param_1() throw() { > std::printf("(%p)-param_1::~param_1()\n", > reinterpret_cast<void*>(this)); > } > > private: > void callback() const { > (m_obj->*(m_mfptr))(m_p1); > } > > static void sys_callback(void const* const state) { > static_cast<param_1 const*>(state)->callback(); > } > }; > } > > > typedef sys::base_pod const& handle; > > > template<typename T, typename T_mfptr, typename T_p1> > sys::param_1<T, T_mfptr, T_p1> > create(T _this, T_mfptr mfptr, T_p1 p1) { > return sys::param_1<T, T_mfptr, T_p1>(_this, mfptr, p1); > } > } > > > struct object { > void func(int i) { > std::printf("(%p)-object::func1(%d)\n", > reinterpret_cast<void*>(this), i); > } > }; > > > struct holder { > func_ptr::handle m_fptr; > holder(func_ptr::handle fptr) : m_fptr(fptr) {} > }; > > > > > int main() { > object obj; > > { > std::puts("Scope 1:\n"); > func_ptr::handle h(func_ptr::create(&obj, &object::func, 123)); > h.execute(); > } > > std::puts("\n\n--------------------------------------------"); > > { > std::puts("Scope 2:\n"); > holder h(func_ptr::create(&obj, &object::func, 123)); > h.m_fptr.execute(); > } > > > /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~*/ > std::puts("\n\n--------------------------------------------\n\ > Press <ENTER> to exit..."); > std::getchar(); > return 0; > } > > __________________________________________________ __________________ > > > > > > Here is the output I get: > __________________________________________________ __________________ > Scope 1: > > (0022FF30)-param_1::param_1() > (0022FF5F)-object::func1(123) > (0022FF30)-param_1::~param_1() > > > -------------------------------------------- > Scope 2: > > (0022FF30)-param_1::param_1() > (0022FF30)-param_1::~param_1() > (0022FF5F)-object::func1(123) > > > -------------------------------------------- > Press <ENTER> to exit... > > __________________________________________________ __________________ > > > > > I am wondering why the const reference in 'Scope 2' (e.g., > holder::m_fptr) is getting destructed _before_ the call to > 'h.m_fptr.execute()'? I thought the output should be identical to > that of 'Scope 1'... What exactly am I doing wrong here? I am > screwing something up somewhere... What can be done to resolve this > issue? > > Yikes! ;^(... The difference is that in Scope 1 you're initialising a local variable that has a reference to const type directly by a temporary. The life of that temporary is extended to the end of the scope, but in Scope 2 you're initialising the reference to const that itself is an argument to the c-tor, so the life of the temporary is limited to the expression that is used to initialise the 'h' object. The member 'm_fptr' of the 'h' object (it's a reference that you copy-initialise from the argument) becomes invalid as soon as the initialisation is complete. The temp object is destroyed. A call to .execute() has undefined behaviour. Here is the model of your code, in simpler terms: #inlcude <iostream> struct A { void foo() { std::cout << "A::foo\n"; } }; struct B { A const &a; B(A const &a) : a(a) {} }; A makeA() { return A(); } int main() { { // Scope 1 A const& ra(makeA()); ra.foo(); } { // Scope 2 B b(makeA()); // problem - the temporary dies here b.a.roo(); // and here you're trying to use it } } In my Scope 1 'ra' is a reference to the temporary object. In my Scope 2 'b.a' is a reference to the temporary object, but it is not initialised _directly_ by binding to the temporary, it's _copy-initialised_ with a _temporary_ reference to A, which in turn is bound to the temporary. The lifetime of the temporary 'A' in Scope 2 _would_ be extended if the reference (the argument to the B's c-tor) survived beyond the initialisation expression. It does not. HTH V -- Please remove capital 'A's when replying by e-mail I do not respond to top-posted replies, please don't ask |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
"Victor Bazarov" <v.Abazarov@comAcast.net> wrote in message
news:ftgnqh$sn8$1@news.datemas.de... > Chris Thomasson wrote: >> Here is the code which should compile fine; program output and my >> question follows: >> __________________________________________________ __________________ [...] >> __________________________________________________ __________________ >> >> >> >> >> I am wondering why the const reference in 'Scope 2' (e.g., >> holder::m_fptr) is getting destructed _before_ the call to >> 'h.m_fptr.execute()'? I thought the output should be identical to >> that of 'Scope 1'... What exactly am I doing wrong here? I am >> screwing something up somewhere... What can be done to resolve this >> issue? >> >> Yikes! ;^(... > > The difference is that in Scope 1 you're initialising a local variable > that has a reference to const type directly by a temporary. The life > of that temporary is extended to the end of the scope, but in Scope 2 > you're initialising the reference to const that itself is an argument > to the c-tor, so the life of the temporary is limited to the expression > that is used to initialise the 'h' object. The member 'm_fptr' of the > 'h' object (it's a reference that you copy-initialise from the argument) > becomes invalid as soon as the initialisation is complete. The temp > object is destroyed. A call to .execute() has undefined behaviour. [...] Ahh. Okay. For some reason I was erroneously thinking that the lifetime of the const-reference would somehow be "extended" across the copy-initialize and finally into the 'holder::m_fptr' member variable, and only be destroyed when the 'holder' object was finally destructed. Thanks for the lesson! :^) |
|
![]() |
| Outils de la discussion | |
|
|