【问题标题】:Reference and Right-Reference with pointers [duplicate]带指针的引用和右引用[重复]
【发布时间】:2018-07-24 23:14:13
【问题描述】:

我在 C++ 设计模式教程中找到了以下代码:

  vector<Object*> objects;
  void foo() override
  {
    cout << "Group contains:\n";
    for (auto&& o : objects)
      o->foo();
  }

在循环中使用右引用的目的是什么?我知道它用于避免临时对象的复制并实现移动语义,但我看不出它在这种情况下如何应用以及为什么不使用简单的

for (auto o : objects)
  o->foo();

另外如果使用auto&o会发生什么?所有这些可能性都正确编译并产生正确的结果......

【问题讨论】:

  • auto&amp;&amp; 表示“除非需要,否则不要复制,否则我不在乎这是复制还是深度引用”。

标签: c++ c++11 foreach reference auto


【解决方案1】:

for (auto o : objects) 将创建提到的副本,因为它使用值语义来获取对象。您可以使用auto&amp; o 来避免这种情况。

但是,如果取消引用迭代器(由范围 for 自动完成)返回一些代理对象(通常:按值返回),这将不起作用。一个例子可能是std::vector&lt;bool&gt;,它使用such "proxy reference"

那么,这将不起作用:

std::vector<bool> vec;
for (auto& v : vec) // fail
{
  ...
}

因为您不能将右值引用绑定到非 const 左值引用。因此,您可以使用通用引用来解决此问题:

std::vector<bool> vec;
for (auto&& v : vec) // ok
{
  ...
}

在您发布的示例中,vector 持有指向对象的指针,因此没有实际区别 - 如果您不想修改内容(因此,不需要通过引用获取指针),使用 value非常好,因为复制指针只会导致其值被复制,而不是指针。所以没有真正的收获。使用右值引用也没有任何优势,除了它正确地传播对象const-ness 并且如果您更改元素向量存储的类型更防弹(它仍然会给您正确的类型,无论*iterator 返回const/non-const 左值/右值引用)。


更新:实际上,我刚刚发现了类似的问题,答案与我提供的几乎相同的示例。 Link.

【讨论】:

  • 那么,为什么auto&amp;&amp;vector&lt;Object*&gt; objects; 一起使用?
  • 这不能回答问题。由于向量是指针向量,因此对我来说复制看起来不错。
  • @freakish 对于指针,使用 rv ref 没有任何好处,除了代码更防弹,并且如果更改,将正确调整自身以适应对象的类型。更新。我真的很好奇什么值得投反对票。
  • 仍然不清楚在哪种情况下它会有用,以及在使用指针时它是否有真正的优势......但我想我不必太在意它:)
  • @giuseppe 恕我直言,最好明确指定如何引用您迭代的对象。使用 const/non-const 或 ref/value 取决于您想要获得什么样的访问权限。使用右值引用仅在临时对象的情况下才有意义,就像我提供的示例一样。否则不清楚其意图是什么,因为没有技术上的理由这样做。
【解决方案2】:

在循环中使用右引用的目的是什么?

在基于范围的循环中使用auto&amp;&amp; 作为通用引用有几个优点:

  • const 传播到迭代元素

  • 更好的可维护性:如果您更改了容器所包含的元素,它会做正确的事情。如果您要更改为std::vector&lt;Object&gt;,它仍然会获得参考而不是副本(如果您使用的是for(auto o : objects)

关于auto 以及在哪里使用它已经说了很多。我特别喜欢 Herb Sutter 的 this talk,他提倡使用它并提供了一些很好的指导。

【讨论】:

  • 是的,维护是一个有效的论据。因为我认为在特定情况下auto o 很好。但这对变化很不利。
  • “更好的可维护性”是什么意思?如果我从 std::vector 更改为 std::vector 那么我需要将我的代码从使用 o.foo() 更改为 o->foo()...
  • @giuseppe 仍然只需要将 -&gt; 更改为 . 并且您不必担心 auto
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-28
  • 1970-01-01
  • 2021-05-14
  • 2011-06-14
  • 1970-01-01
  • 2014-10-12
  • 2010-10-19
相关资源
最近更新 更多