简体   繁体   中英

How to get the address of the return value of a function in C++

Given this prototype which does a Endian conversion:

time_t Flip( time_t );

I would like to use the return value in a function that takes a BYTE* as an argument. Something like this:

SetBytesAt( 0, (BYTE*)&(Flip( t )) );

But this does not compile. Gives me this error "& requires l-value". If the () are removed from around the Flip function, the same error is generated.

Now, I know that I can just do this:

time_t temp_t = Flip( t );
SetBytesAt( 0, (BYTE*)&temp_t );

But it seems to me that I should be able to accomplish the same thing without the temporary temp_t variable.

Unfortunately, no. You cannot take the address of a temporary (more correctly, an r-value ). That's just the way the language has been defined.

Don't try this at home.

template <typename T>
class AddressableTemporary
{
public:

    AddressableTemporary(T const value)
        : value_(value)
    {
    }

    operator T*() { return &value_; }

private:

    T value_;
};

template <typename T>
AddressableTemporary<T> MakeAddressable(T value)
{
    return AddressableTemporary<T>(value);
}

Used as:

int  F() { return 42; }
void G(int const* const p) { std::cout << *p; }

int main()
{
    G(MakeAddressable(F()));
}

But really, don't do this. Either use a variable, or write a wrapper function that encapsulates usage of the variable, or rework your code so that you don't need to worry about this (eg, modify the function so that it takes, say, a const reference).

To the best of my knowledge, that is not possible in C++.

Ask yourself this: how will you access the modified result after SetBytesAt returns?

Return values are normally copied (or moved) to an actual variable in the caller function. The temporary space reserved for the returned value is no longer available after the function returns. Theoretically, you would be stack memory that is no longer valid. This mistake happens in practice when returning references to local variables.

You need to use a temporary variable. You can only take address of l-values. There is no way to take address of a return value.

On some platforms, return value is only stored in a register and hence doesn't even have an address. You need to store it in memory before you can pass its address to another function.

You can't, for the exact reason given by the error message - & requires l-value .

The call Flip(t) is not an l-value, so it's impossible.

Actually, it became possible in C++11. There, r-value references were introduced. However, I don't know, which compiler does it already.

It's no big deal to do what you want, but it's unclean.

Here goes:

template< class Type >
Type const& ref( Type const& v ) { return v; }

int main()
{
    time_t t = blah blah;
    SetBytesAt( 0, const_cast<Byte*>( reinterpret_cast<Byte const*>( &ref( Flip( t ) ) ) ) );
}

Technically this can work if SetBytesAt copies the bytes, but if SetBytesAt stores the pointer, and that pointer is later used, then it's undefined behavior.

Anyway, don't do that.

Now I'll list what's wrong with the original concept:

  • Discarding type knowledge by using typeless pointer argument.
    → Means a lot of extra work because the type is not known.

  • Discarding const knowledge by using pointer to non-const argument.
    → Means a lot of extra work because the constness is not known.

  • Flipping byte order of data = ungood except in low level network code.
    → Means a lot of extra work because the byte order is not known.

So, again, don't do that.

Instead, do the opposite: preserve type information, preserve constness information, and don't mess with the raw bytes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM