【问题标题】:Are unnamed objects and temporary objects equivalent?未命名对象和临时对象是否等效?
【发布时间】:2012-12-05 18:09:51
【问题描述】:

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

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

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

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

我的问题是:未命名的对象总是临时的吗?临时对象总是未命名吗?

换句话说:未命名对象和临时对象是否等价

【问题讨论】:

  • 我不太了解技术术语,无法作为答案发布,但我认为这是一个反例:void foo(int) {}。这里的参数是一个不是临时的,但没有名字的对象。
  • 好点。这个例子似乎清楚地表明,与右值引用相关的是 temporary 对象 - 而不是 unnamed 变量。
  • 真的有“未命名对象”的定义吗?
  • 我想知道“临时对象”的定义(以及...)

标签: c++


【解决方案1】:

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

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

int main()
{ foo(5); }

foo() 的参数是未命名的,但它不是临时的。因此,未命名对象和临时对象是不等价的。

【讨论】:

    【解决方案2】:

    可以命名临时对象。

    非常常见的情况 - 当作为参数传递给函数时。 另一种不太常见的情况 - 将 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创建的任何对象。

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

    【讨论】:

      【解决方案3】:

      我一直在思考什么时候编译器会确定一个特定的函数参数是一个右值引用,什么时候它会确定它是一个左值引用。

      我假设您在谈论具有通用引用参数的函数模板,像这样?

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

      规则非常简单。如果参数是X 类型的右值,那么T 将被推导出为X,因此T&amp;&amp; 表示X&amp;&amp;。如果参数是X 类型的左值,那么T 将被推导出为X&amp;,因此T&amp;&amp; 表示X&amp; &amp;&amp;,它被折叠成X&amp;

      如果你真的问的是参数,那么这个问题没有多大意义,因为参数从来都不是左值引用或右值引用,因为X&amp; 类型的表达式会立即转换为X 类型的表达式,表示被引用的对象。

      但是,如果您实际上的意思是“编译器如何区分左值参数和右值参数?” (注意缺少的reference),那么答案很简单:编译器知道每个表达式的值类别,因为标准为每个可能的表达式指定了它的值类别是什么。例如,函数的调用是可以属于三个值类别之一的表达式:

      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

      【讨论】:

      • 快速跟进:假设你有int x; int &amp; y = x;y的类型被认为是-int还是int &amp;
      • 答案取决于您正在与谁交谈以及您目前正在考虑使用哪种语言功能 :) 例如,decltype(y)decltype((y)) 都是 int&amp;,但我认为 decltype 是唯一将某物的类型视为参考的情况。如我错了请纠正我!该标准说“如果一个表达式最初具有类型“对 T 的引用”(8.3.2、8.5.3),则在任何进一步分析之前将该类型调整为 T。表达式指定引用表示的对象或函数,并且表达式是左值或 xvalue,具体取决于表达式。"
      • 回复。我之前的评论:即,给定 class A; void foo(A&amp;&amp; a_); int main() { foo(A()); } - parameter 类型是 rvalue 引用,对应于 A()argument typervalue,而a_对应的argument type是(有趣的)一个lvalue,对吗?
      • 您必须注意不要将类型与值类别混淆。参数typeA&amp;&amp;(对A的右值引用),参数value category是左值。所有参数都是左值,无论它们的类型如何,因为所有参数都有名称,并且大多数名称都是左值。参数typeA,参数value category是prvalue。
      • 跟进...我非常强烈推荐@FredOverflow 的链接文章(在他的回答底部);它非常出色,并且(尽管他评论说它“有点相关”,他可能是因为他自己在链接中写了这篇文章所以他被低估了所以他写的),它详细涵盖了整个主题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-30
      • 2016-04-13
      • 2017-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多