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

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

本文关键字:函数 返回值 地址 获取 C++      更新时间:2023-10-16

给定这个进行Endian转换的原型:

time_t Flip( time_t );

我想在一个以BYTE*为参数的函数中使用返回值。类似这样的东西:

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

但这并不能编译。给我这个错误"&requires l-value"。如果从Flip函数周围删除(),则会生成相同的错误。

现在,我知道我可以这么做:

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

但在我看来,如果没有临时的temp_t变量,我应该能够完成同样的事情。

不幸的是,没有。您不能获取临时地址(更准确地说,是r值)。这就是语言的定义方式。

不要在家里尝试。

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);
}

用作:

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

但实际上,不要这样做。要么使用一个变量,要么编写一个封装变量使用情况的包装函数,要么重新编写代码,这样就不必担心这一点(例如,修改函数,使其获得常量引用)。

您需要使用一个临时变量。您只能获取l-value的地址。并没有办法获取返回值的地址。

在某些平台上,返回值只存储在寄存器中,因此甚至没有地址。您需要将其存储在内存中,然后才能将其地址传递给另一个函数。

据我所知,这在C++中是不可能的。

问问自己:SetBytesAt返回后,您将如何访问修改后的结果?

返回值通常被复制(或移动)到调用函数中的实际变量。函数返回后,为返回值保留的临时空间将不再可用。从理论上讲,您将是不再有效的堆栈内存。在实践中,当返回对局部变量的引用时,会发生这种错误。

实际上,它在C++11中成为可能。在那里,引入了r值参考。然而,我不知道是哪个编译器已经做到了。

由于错误消息-& requires l-value给出的确切原因,您不能。

调用Flip(t)不是一个l值,所以这是不可能的。

做你想做的事没什么大不了的,但它是不干净的。

如下:

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 ) ) ) ) );
}

从技术上讲,如果SetBytesAt复制字节,这是可行的,但如果SetBytesAt存储指针,并且该指针后来被使用,那么这是未定义的行为。

不管怎样,不要那样做。

现在我将列出原始概念的错误:

  • 使用无类型指针参数丢弃类型知识
    →这意味着要做很多额外的工作,因为类型未知。

  • 通过使用指向非常量参数的指针来丢弃常量知识
    →这意味着要做很多额外的工作,因为常量未知。

  • 翻转数据的字节顺序=不正常,低级别网络代码除外
    →由于字节顺序未知,这意味着要做很多额外的工作。

所以,再一次,不要那样做。

相反,做相反的事情:保留类型信息,保留常量信息,并且不要干扰原始字节。