Sign in to follow this  

Undefined C++, yet why?

This topic is 3599 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

This topic is 3599 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this