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

时间:2012-03-27 20:07:54

标签: c++

鉴于此原型进行了Endian转换:

time_t Flip( time_t );

我想在一个以BYTE *作为参数的函数中使用返回值。 像这样:

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

但是这不能编译。给我这个错误“&需要l值”。 如果从Flip函数周围删除(),则会生成相同的错误。

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

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

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

7 个答案:

答案 0 :(得分:9)

不幸的是,没有。你不能拿一个临时的地址(更准确地说是r-value)。这就是语言定义的方式。

答案 1 :(得分:3)

不要在家里试试。

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

但实际上,不要这样做。要么使用变量,要么编写封装变量用法的包装函数,或者重新编写代码,这样就不必担心这个问题(例如,修改函数使得它需要一个const引用)。

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:0)

您需要使用临时变量。您只能获取l值的地址。无法获取返回值的地址。

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

答案 4 :(得分:0)

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

电话Flip(t)不是l值,所以不可能。

答案 5 :(得分:0)

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

答案 6 :(得分:0)

做你想做的事并没什么大不了的,但这是不洁净的。

这里是:

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存储指针,并且稍后使用该指针,则它是未定义的行为。

无论如何,不​​要这样做。

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

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

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

  • 翻译数据的字节顺序= ungood除了低级网络代码外 →意味着很多额外的工作,因为字节顺序是未知的。

所以,再说一次,不要这样做。

相反,执行相反的操作:保留类型信息,保留constness信息,并且不要弄乱原始字节。