Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Address of return value of method

I have a get-method that returns a value:

int Foo::getValue() const
{
    return value_;
}

I'm using the following code to write this value to a binary file:

void Bar::write(const Foo& foo)
{
    /* some code... */

    file_.write(reinterpret_cast<char*>(&foo.getValue()), sizeof(int));
}

And it seems that everything works well. But I am not sure about that &foo.getValue() thing. Will it always return an address of return value of getValue() or are there any pitfalls?

EDIT1: I dont want to create a temporary var for this.

EDIT2: Yes, it compiles and works fine.

EDIT3: write is a ostream::write

EDIT4: With /Wall and /Za it will not compile: error C2102: '&' requires l-value

like image 339
NekoUnderscore Avatar asked Dec 21 '15 18:12

NekoUnderscore


2 Answers

The standard forbids you to take the address of an rvalue: https://stackoverflow.com/a/28459180/2642059 A compiler that is not standard compliant may allow this behavior, but assuredly that is not behavior that will be cross platform, nor is it guaranteed to succeed even between updates to the compiler that may more closely align it with the C++ standard.

Since you are not programming for a specific compiler, but for C++, finding something that works in a specific compiler should not be your objective. Finding a way to accomplish this within the standard would be preferable.

A couple easy options for doing that would be:

  1. Turn it into an lvalue by assigning it to a temporary value. They're free! The compiler will optimize them right out
  2. Change the return of getValue to const int& this will allow you to work with an lvalue. Since ints are typically copied by value this probably will not have repercussions in your code base, but it could
  3. Create another method which could directly return (const char*)&value_, you could get in trouble abusing this one though so be careful
like image 145
Jonathan Mee Avatar answered Oct 17 '22 15:10

Jonathan Mee


Microsoft Compiler for whatever reason has a `"feature" - it implicitly converts temporary to lvalue. You can check it by this code:

int &ref = foo.getValue();

this code as well as your should not compile. Proper code would be:

void Bar::write(const Foo& foo)
{
    /* some code... */
    int temp = foo.getValue();
    file_.write(static_cast<const char*>(&temp), sizeof(int));
}
like image 32
Slava Avatar answered Oct 17 '22 15:10

Slava