Undefined C++, yet why?

Started by
1 comment, last by dmail 16 years, 2 months ago
I do not have a version of the standard available to me currently so I can not quote why I think this should be valid and find why it may not, so I am asking if anybody knows the reason. The following code is only for demonstration purposes:

struct Foo
{
   Foo(int const& i):m_i(i){}
   int m_i;
};

struct Foo_ref
{
  Foo_ref(int const& i):m_foo(i){}
  operator Foo const&()const {return m_foo;}
  Foo m_foo;
};

struct Bar
{
  Bar(int const & i):m_foo( Foo_ref(i*2) ){}
  Bar(Bar const & rhs):m_foo( rhs.m_foo ){}
  int value(){return m_foo.m_i;}
private:
  Foo const& m_foo;
};

#include <iostream>

int main(int /*argc*/, char* /*argv[]*/)
{

 	Bar bar(5);
 	Bar bar2(bar);
 	std::cout <<bar.value() <<" " << bar2.value() <<std::endl;
 	return 0;
}

The above code is valid as a reference can be instigated using a type different from the reference type if it can be converted to the reference type. Also a constant reference bound to a temporary extends the life of the temporary, so I would expect the constant reference returned by Foo_ref to also extend the life of its internal Foo instance. Yet if we adjust the code to be able to change the value of the int inside the object Foo, via a constant function and using the mutable keyword then all bets are off. I can only conclude this maybe due to the reference being put in a none writeable area, should the following fail or not?

struct Foo
{
   Foo(int const& i):m_i(i){}
   void add(int const & i)const
   {
   		m_i += i;
   }
   mutable int m_i;
};

struct Foo_ref
{
  Foo_ref(int const& i):m_foo(i){}
  operator Foo const&()const {return m_foo;}
  Foo m_foo;
};

struct Bar
{
  Bar(int const & i):m_foo( Foo_ref(i*2) ){}
  Bar(Bar const & rhs):m_foo( rhs.m_foo ){}
  int value(){return m_foo.m_i;}
  void add(int const& i){m_foo.add(i);}
private:
  Foo const& m_foo;
};

}
#include <iostream>

int main(int /*argc*/, char* /*argv[]*/)
{
 	Bar bar(5);
 	Bar bar2(bar);
 	std::cout <<bar.value() <<" " << bar2.value() <<std::endl;
 	bar.add(2);
 	std::cout <<bar.value() <<" " << bar2.value() <<std::endl;
 	return 0;
}

Yes I know this is really trying to abuse the language and in the second instance is. Thanks.
Advertisement
Even your first example is undefined behaviour. Binding a temporary to a reference extends the lifetime of the temporary to the lifetime of the reference or to the end of the scope in which the temporary is created, whichever is shorter. Additionally:
Quote:C++ Standard, Section 12.2, Paragraph 5
<snip /> A temporary bound to a reference member in a constructor's ctor-initializer (12.6.2) persists until the constructor exits. <snip />

Σnigma
That would explain it thank you.

This topic is closed to new replies.

Advertisement