【问题标题】:Range-based for loop with decltype(auto)使用 decltype(auto) 的基于范围的 for 循环
【发布时间】:2016-07-17 12:49:43
【问题描述】:

在使用基于范围的 for 循环时,是否存在decltype(auto)auto(可能带有 &&& 或 cv 限定符)更好的选择?换句话说,你会写下面的代码吗?

for (decltype(auto) item : range) {
    // ...
}

【问题讨论】:

    标签: c++ for-loop c++14 auto decltype


    【解决方案1】:

    decltype(auto) 在输入迭代器按值返回时生成不同的类型。 auto&& 创建一个对临时对象的右值引用,而decltype(auto) 创建一个本地副本(在 C++17 中,它只是命名临时对象,因为保证了省略更改)。

    这没什么区别。在 C++11/14 中,在 decltype(auto) 情况下,它需要一个移动 ctor(在实践中没有调用,但需要),但在 C++17 中不需要。在 auto&& 中,移动 ctor 未被调用且不需要。

    另一个区别是decltype(item) 的类型,它始终是auto&& 的引用,但在临时返回输入迭代器的情况下decltype(item) 是值类型。

    就是这样。在实践中,我认为没有理由 decltype(auto) 超过 auto&&

    顺便说一句,auto& 强制非右值,const auto& 强制非可变,auto 强制复制。有理由使用 auto&& 而不是那些,但这超出了这个问题的范围。 decltype(auto) 最接近 auto&&,所以我比较了这两个。

    【讨论】:

    • auto&& 是右值引用吗?我认为这是一个通用/转发参考。不声称你错了——只是想学习。 :)
    • @erip :它确实是一个转发引用——“当输入迭代器按值返回时”然后它创建一个右值引用。 ;-]
    • 完全忽略了这一点。糟糕!
    【解决方案2】:

    如上所述here

    decltype(auto) 主要用于推断转发函数和类似包装器的返回类型

    [...]

    虽然它可以用来声明局部变量,但这样做可能只是一种反模式,因为局部变量的引用不应该依赖于初始化表达式

    也就是说,在基于范围的 for 循环中使用 转发引用 是可行的方法。
    如前所述here

    在泛型代码中使用推导来转发引用是安全的,事实上,更可取

    我建议在 SO 上提出this 问题,以获取有关在基于范围的 for 循环中使用通用引用的更多详细信息。

    【讨论】:

    • "除了它们目前被命名为通用引用这一事实之外,该注释仍然有效。" 你倒过来了——迈耶斯给了它们一个临时名称“通用引用” ',但从 C++17 开始,标准本身正式将它们命名为“转发引用”。
    • @ildjarn 你完全正确。我要修复答案。我曾经把这两种形式弄错了。对不起,谢谢。
    猜你喜欢
    • 2013-06-06
    • 2016-10-31
    • 2015-01-15
    • 1970-01-01
    • 2016-04-03
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多