简体   繁体   English

如何在C ++中获取函数返回值的地址

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

Given this prototype which does a Endian conversion: 鉴于此原型进行Endian转换:

time_t Flip( time_t );

I would like to use the return value in a function that takes a BYTE* as an argument. 我想在一个以BYTE *作为参数的函数中使用返回值。 Something like this: 像这样的东西:

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

But this does not compile. 但这不编译。 Gives me this error "& requires l-value". 给我这个错误“&需要l值”。 If the () are removed from around the Flip function, the same error is generated. 如果从Flip函数周围删除(),则会生成相同的错误。

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. 但在我看来,如果没有临时的temp_t变量,我应该能够完成同样的事情。

Unfortunately, no. 抱歉不行。 You cannot take the address of a temporary (more correctly, an r-value ). 你不能取一个临时的地址(更准确地说,是一个r值 )。 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). 要么使用变量,要么编写封装变量用法的包装函数,或者重新编写代码,这样就不必担心这个问题(例如,修改函数使得它需要一个const引用)。

To the best of my knowledge, that is not possible in C++. 据我所知,这在C ++中是不可能的。

Ask yourself this: how will you access the modified result after SetBytesAt returns? 问问自己:在SetBytesAt返回后如何访问修改后的结果?

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. 您只能获取l值的地址。 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 . 由于错误消息给出的确切原因,您不能 - 并且& requires l-value

The call Flip(t) is not an l-value, so it's impossible. 调用Flip(t)不是l值,因此不可能。

Actually, it became possible in C++11. 实际上,它在C ++ 11中成为可能。 There, r-value references were introduced. 在那里,引入了r值参考。 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. 从技术上讲,如果SetBytesAt复制字节,这可以工作,但如果SetBytesAt存储指针,并且稍后使用该指针,那么它是未定义的行为。

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. 通过使用指向非const参数的指针来丢弃const知识。
    → Means a lot of extra work because the constness is not known. →意味着很多额外的工作,因为常数是未知的。

  • Flipping byte order of data = ungood except in low level network code. 除低级网络代码外,翻转数据的字节顺序= ungood。
    → 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. 相反,执行相反的操作:保留类型信息,保留constness信息,并且不要弄乱原始字节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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