I’m trying to understand exact C++ (pre C++0x) behavior with regards to references and rvalues. Is the following valid?
void someFunc ( const MyType & val ) {
//do a lot of stuff
doSthWithValue ( val);
}
MyType creatorFunc ( ) {
return MyType ( "some initialization value" );
}
int main () {
someFunc ( creatorFunc() );
return 0;
}
I found similar code in a library I’m trying to modify. I found out the code crashes under Visual Studio 2005.
The way I understand the above, what is happening is:
creatorFunc is returning by value, so a temporary MyType object obj1 is created. (and kept… on the stack?)
someFunc is taking a reference to that temporary object, and as computation progresses the temporary object is overwritten/freed.
Now, what is mind-boggling is that the code most often works fine. What is more, with a simple piece of code I cannot reproduce the crash.
What is happening/supposed to happen here? Does is matter if the reference (val) is const or not? What is the lifespan of the object returned from creatorFunc?
The return value has the lifetime of a temporary. In C++ that means the complete expression that created the type, so the destructor of MyType shouldn’t be called until after the call to someFunc returns.
I’m curious at your ‘is overwritten/freed’. Certainly calling delete on this object is not OK; it lives on the stack and deleting it would probably cause heap corruption. Also, overwriting/modifying it could also be bad. Your example uses a constant “C string”; on many compilers values like this are stored in read-only memory, so attempting to modify it later could cause a crash/access violation. (I’m not sure if Visual C++ does this optimization, however).
There is a big difference between passing a temporary by const versus mutable references. Creating a mutable reference to a temporary is not allowed by standard C++, and most compilers (including GCC) will reject it, though at least some versions of Visual C++ do allow it.
If you are passing it with a mutable reference, what you want to write is: