C++20 改进了 for 循环语法
C++20 Improved the For-Loop Syntax

原始链接: https://lzon.ca/posts/tips/cpp-for-range-init/

C++20 引入了一项实用的语法糖:**带初始化的范围遍历循环**(range-based for loops with initializers)。 在 Python 和 Lua 等语言中,遍历集合的同时追踪索引和元素非常简单。过去,C++ 需要更繁琐的语法才能实现同样的效果。借助 C++20 的这项新特性,开发者现在可以将初始化语句与范围遍历循环结合起来,达到了与其他现代语言一样优雅且简洁的效果。 其语法如下: ```cpp for (int i = 0; auto&& it : vec) cout << (++i) << ": " << it << endl; ``` 受 C++17 引入的“带初始化的 if 语句”启发,这次更新是一项虽小但影响深远的易用性改进。虽然看似微不足道,但当此类增强功能应用于整个代码库时,能显著提升代码的可读性和可维护性。这一新增功能凸显了 C++ 标准委员会为通过实用、友好的特性来推动语言现代化所做的不懈努力。

这篇 Hacker News 帖子讨论了关于 C++20 中改进版 for 循环语法的文章。用户们争论了这一更新是否提供了显著的便利性,一些人批评它仍需手动递增计数器,感觉像是“伪装成 for 循环的 while 循环”。 参与者对比了 C++ 的复杂性与 Python 和 Lua 等语言的简洁性。虽然一些人认为 C++20 的新语法是不必要的冗余,但另一些人则指出,像 `std::views::enumerate`(C++20)和 `std::println`(C++23)等现代特性,是实现类似 Python 功能更好、更地道的方式。 对话最后对 C++ 的复杂性进行了更广泛的批评。用户认为该语言过于庞大,开发人员必须依赖严格的风格指南或“子集”来管理其冗余,并引用 Google 的 C++ 风格指南作为开发人员限制该语言庞大功能集以维持代码质量的典型案例。
相关文章

原文

A small piece of syntactic sugar from C++20.


Let’s say I wanted to print out the following:

1: the
2: quick
3: brown
4: fox
5: jumped
6: over
7: the
8: lazy
9: dog

If I had to use Python, I’d write something like this:

vec = [
    "the", "quick", "brown", "fox", 
    "jumped", "over", "the", "lazy", "dog"
]



for i, it in enumerate(vec, start=1):
    print(f"{i}: {it}")

And if I were to use Lua, it might look like this:

local vec = { 
    "the", "quick", "brown", "fox", 
    "jumped", "over", "the", "lazy", "dog" 
}



for i, it in ipairs(vec) do
    print(i .. ": " .. it)
end

But if I were to use C++17 or older, the equivalent approach would look like this:

vector<string> vec = { 
    "the", "quick", "brown", "fox", 
    "jumped", "over", "the", "lazy", "dog" 
};



for (int i = 0; i < vec.size(); ++i)
{
    auto&& it = vec[i];
    cout << i << ": " << it << endl;
}

The common theme of these examples is that they produce a for-loop that includes in its scope both an index value and element reference. C++ stands out for having to introduce the reference to it’s loop scope with an additional statement.

With C++20, it is now possible to create an example that matches the other languages, and it looks like this:

vector<string> vec = { 
    "the", "quick", "brown", "fox", 
    "jumped", "over", "the", "lazy", "dog" 
};



for (int i=0; auto&& it: vec)
    cout << (++i) << ": " << it << endl;

The specific proposal that enables this is called Range-based for statements with initializer, and it is very similar to a previous proposal from C++17, If statement with initializer. What I have demonstrated in this post is precisely the intended use-case for this language feature.

I really like it. It may seem very trivial, but small pieces of syntactic sugar like this pay large dividends when used across an entire codebase. I’ve only just discovered it myself, but I intend to use it exclusively over the traditional approach going forward.


It seems to me that the C++ Standards Committee is doing a decent job maintaining the language, and introducing useful features when it makes sense to do so. Have you discovered any small quality-of-life features such as this? If so, let me know!

Send a message to [email protected], or DM me on one of my social accounts on the homepage.
联系我们 contact @ memedata.com