未命名的对象和临时对象是否相同?

时间:2012-12-05 18:09:51

标签: c++

在我理解rvalue引用的过程中,我一直在思考编译器何时确定某个特定的函数参数是一个右值引用,以及它何时将它确定为左值引用。

(此问题与参考折叠有关;请参阅Concise explanation of reference collapsing rules requested: (1) A& & -> A& , (2) A& && -> A& , (3) A&& & -> A& , and (4) A&& && -> A&&)。

特别是,我一直在考虑编译器是否始终将未命名对象视为右值引用和/或编译器总是将临时对象视为右值引用。

反过来,这让我怀疑未命名的对象是否等同于临时对象。

我的问题是:未命名的对象总是暂时的;并且是永远未命名的临时对象?

换句话说:未命名的对象和临时对象是等同于吗?

3 个答案:

答案 0 :(得分:3)

我可能错了,因为我不确定“未命名对象”的定义是什么。但请考虑下面的foo()函数的参数:

void foo(int)
{ /* ... */ }

int main()
{ foo(5); }

foo()的论点是未命名的,但它不是暂时的。因此,未命名的对象和临时对象不等效。

答案 1 :(得分:3)

可以命名临时对象。

非常常见的情况 - 作为参数传递给函数时。 另一种不太常见的情况 - 将const引用绑定到函数的右值结果。

int f(int i) { return i + 1; }
int g() { const int &j = f(1); return j; }

未命名的对象通常是临时的,但并非总是如此。例如 - 匿名联合对象:

struct S
{
   union { int x; char y; };
} s;

当然,还有operator new创建的任何对象。

也许还有其他案例,但即使只有这些案例可以作为假设的反例:)

答案 2 :(得分:2)

  

我一直在思考编译器何时确定某个特定的函数参数是一个右值引用,以及何时它将它确定为左值引用。

我假设您正在讨论具有通用参考参数的功能模板,如下所示?

template<typename T>
void foo(T&& t)
{
}

规则很简单。如果参数是X类型的右值,则T将推断为X,因此T&&表示X&&。如果参数是X类型的左值,那么T将推断为X&,因此T&&表示X& &&,它会折叠为X& 1}}。

如果您真的在询问参数,那么问题没有多大意义,因为参数永远不是左值引用或右值引用,因为类型X&的表达式会立即被转换表达式为X的表达式,表示引用的对象。

但是,如果你真的意味着“编译器如何区分左值参数和右值参数?” (注意缺少的引用),然后答案很简单:编译器知道每个表达式的值类别,因为标准为每个可想到的表达式指定了它的值类别。例如,函数的调用是一个表达式,它可以属于以下三个值类别之一:

X   foo();   // the expression foo() is a prvalue
X&  bar();   // the expression bar() is an lvalue
X&& baz();   // the expression baz() is an xvalue

(当然,前提是X本身不是引用类型。)

如果这些都没有回答您的问题,请澄清问题。另外,somewhat relevant FAQ answer