我在C ++设计模式教程中找到了以下代码:
vector<Object*> objects;
void foo() override
{
cout << "Group contains:\n";
for (auto&& o : objects)
o->foo();
}
在循环中使用右引用的目的是什么?我知道它用于避免临时对象的复制并实现移动语义,但我看不出它在这种情况下是如何应用的,为什么不使用简单的
for (auto o : objects)
o->foo();
此外,如果使用auto&amp; amp; Ø?所有这些可能性都能正确编译并产生正确的结果......
答案 0 :(得分:3)
dialogClassName
将创建提到的副本,因为它使用值语义来获取对象。您可以使用for (auto o : objects)
来避免这种情况。
但是,如果取消引用迭代器(由范围auto& o
自动完成)会返回一些代理对象(通常:按值返回),这将不起作用。一个示例可能是std::vector<bool>
,它使用such "proxy reference"。
然后,这不起作用:
for
因为您无法将rvalue引用绑定到非const左值引用。因此,您可以使用通用引用来解决此问题:
std::vector<bool> vec;
for (auto& v : vec) // fail
{
...
}
在您发布的示例中,std::vector<bool> vec;
for (auto&& v : vec) // ok
{
...
}
包含指向对象的指针,因此没有实际区别 - 如果您不想修改内容(因此,不需要通过引用获取指针),使用值是完全正常的,因为复制指针只会导致其值被复制,而不是指针。所以没有真正的收获。使用右值引用也没有任何优势,除非它正确地传播对象vector
- 并且如果你改变元素向量存储的类型就更加防弹(它仍然会给你正确的类型,无论是否{{ 1}}返回const / non-const lvalue / rvalue reference)。
更新:实际上,我刚刚发现了类似的问题,几乎与我提供的示例相同。 Link
答案 1 :(得分:2)
在循环中使用右引用的目的是什么?
在基于范围的循环中使用auto&&
作为通用引用有几个优点:
const
传播到迭代元素
更好的可维护性:如果您更改了容器所包含的元素,它将做正确的事情。如果您要更改为std::vector<Object>
,它仍会获得引用而不是副本(如果您使用的是for(auto o : objects)
有很多关于auto
和使用它的地方。我特别喜欢Herb Sutter的this talk,他主张使用它并提供一些很好的指导。