鉴于此原型进行了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变量,我应该能够完成同样的事情。
答案 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信息,并且不要弄乱原始字节。