C++安全性的问题(第二部分):现代C++是一种思维模式,而非标准
来源标题:The Problem with C++ Safety (Part 2): Modern C++ Is a Mindset, Not a Standard
文章指出,现代C++的核心并非新标准或新特性,而是默认写出正确、快速、安全的代码的思维模式。作者以回文检测为例,展示用std::equal一行代码即可替代难以阅读的经典C++实现,尽管该算法早在C++98就已存在。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
在这篇文章的第一部分,我们查看了两种判断给定字符串是否为回文的尝试。这两种实现都是用“经典C++”编写的,感觉并不好:代码难以阅读、难以理解,因此缺陷也难以发现。现在是时候继续这个故事,看看一个更好的解决方案,即“现代C++”解决方案。
那么让我们来看一个现代C++的解决方案。
[[nodiscard]] bool is_palindrome( std::string_view str ) return std::equal( str.cbegin(), str.cbegin()+str.size()/2U, str.crbegin() );
是的,就这么简单:只需调用一次std::equal()算法。我们将前向迭代器所表示范围的前半部分与反向迭代器所表示范围的后半部分进行比较。
“但是Klaus,等一下:这个std::equal()算法可是老古董了!它从C++98起就是标准的一部分!这不算现代,对吧?”
如果你是这样想的,那么我有一些重要的信息要告诉你:现代C++不在于新特性或新的C++标准。它在于默认写出正确、快速且安全的代码。它是一种思维方式。所以为了证明我的观点,请你自己问一下之前的问题:你确定没有与安全或安保相关的问题吗?
没有,对吧?而且验证起来如此容易:没有if语句——事实上,根本没有条件语句,没有指针或索引,没有显式循环。它只是一个简单的函数调用。所以这段代码通过检查即可证明是正确的。它默认就是正确的。而且它简单。而且快速。
甚至还有一个更新、更优雅的解决方案:
[[nodiscard]] bool is_palindrome( std::string_view str ) return std::ranges::equal( str, str | std::views::reverse );
这是基于C++20 ranges的解决方案。我们直接在字符串及其反向表示上使用std::ranges::equal()函数。我们甚至不再需要迭代器。诚然,我们现在比较的是整个范围,而不仅仅是前后两半。然而,撇开性能不谈,其简洁性、优雅性以及默认的正确性令人惊叹!这就是我们所称的“现代C++”。
“好吧,Klaus,我同意这更简单而且默认就是正确的。但这真的意味着基于循环的解决方案不好吗?毕竟它能工作,不是吗?”
你说得对,它“能工作”,忽略单字符字符串的未定义行为的话。但它更复杂,验证需要更多精力,编写需要更多时间,阅读和理解更困难,需要相当多的测试,而且默认就不是正确的。所有这些意味着,最终它的成本也高得多。再也没有足够好的理由用这种经典风格来编写它了。这正是我所认为的我们社区中的真正问题。
太多C++开发者尚未接受现代C++,仍然默认使用危险且更易出错的构造。太多C++开发者不知道现代的做事方式,或者无论出于什么原因,仍然更喜欢写更显式的代码。因此,他们默认在C++的“不安全模式”下工作。
在我看来,这是一个教育问题,一个教学问题。几十年来,人们一直写这种经典C++,而且“它没问题”。到现在,人们对这种风格感到太舒适、太熟悉了。这才是真正的问题。
不幸的是,这个问题目前正在显著扩大:随着AI工具的使用,人们自动生成这种经典C++。是的,我有证据:我让ChatGPT为我生成一个is_palindrome()函数(见图1)。你猜怎么着:它给我的几乎就是最初LinkedIn帖子中的那个函数。而且不:它甚至没有考虑建议使用算法。
那么为什么这些现代工具不使用现代方式呢?嗯,尽管名字叫AI,但人工智能与智能无关。它是一个基于统计的工具。如果更多人使用经典方式,那么从统计上讲这就是“正确”的解决方案。所以AI工具更倾向于为你写一个for循环而不是使用算法,这并不奇怪。
我应该诚实地说,这并不适用于市场上的每一个AI工具。有些比其他的更好,有些实际上建议使用算法。然而,不幸的是,这并不能解决问题:AI工具可能建议过时的解决方案,这些方案已不再是最佳实践。
幸运的是,社区中许多人比AI工具更懂,了解现代解决方案。让我借此机会向一些在最初LinkedIn帖子下迅速发布良好现代解决方案的人致敬。非常感谢Alex Dathskovsky和Sergii Rybin发布了基于算法的解决方案。老实说,我们需要更多像你们这样的人来帮助传播当今应该如何做事的信息。非常感谢!
那么我们还能做什么呢?作为一个C++培训师,我可以尽我的一份力:我可以告诉人们。我可以教导人们。我可以向人们展示。这就是我想在Rainer Grimm的博客中做的事情:在接下来的几个月里,我想谈谈C++中现代的做事方式。我想展示我们今天是如何工作的,希望这能带来改变,希望建立现代C++思维方式,并或许(但愿!)有助于让更多人——甚至超越C++社区——普遍认识到,只要我们按C++应有的方式使用它,C++可以是非常安全的。
在接下来的几个月里,我将撰写关于边界安全、类型安全、生命周期安全、初始化安全的内容,并作为特别附加内容——关于未定义行为。我将证明,只需很少的努力,你就可以轻松且默认地避免所有这些安全问题。
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。