消息

c++注释十月2021:cppcon专用播客集,组合字符串和模板,移动与复制,和UDL基础

在最新一期的月刊中,我们为您带来了十月的所有新闻C ++注释消化和它的同伴不需要诊断秀。

如果你已经订阅了,可以直接跳到新闻。如果这是您第一次来这里,让我们快速地带您浏览一下我们提供的所有格式。您可以选择阅读、收听或观看本月c++新闻的精华文摘:

  • 在我们的博客上阅读每月的摘要(使用右边的表单订阅博客)。
  • 通过填写订阅c++注释电子邮件这种形式
  • 不需要诊断展示YouTube.为了确保你能听到新的剧集,在推特上关注我们
  • 听我们的播客-只要在你最喜欢的播客播放器中搜索“不需要诊断”(见支持玩家列表).

cppcon专用NDR播客插曲

本月,我们的版本不需要诊断和我们的常规节目有点不同。有两个原因。首先,我们的同事来自cppact播客最近,我注意到也有其他的c++播客,但并不是很多都是常规的。CppCast和NDR是,但Cpp。闲谈,聊天,hosted by Phil Nash and Jon Kalb, hasn’t been released for a while. So I suggested to Phil, who is the host for both Cpp.Chat and NDR, to record a joint episode to breathe some fresh life into Cpp.Chat. Second,CppCon只是一个星期前举行。作为世界上最大的C ++活动,带来了很多新的C ++洞察力,灵感和知识。在我们的一年半锁定后,在这个混合事件中讨论了很多新事物!与组织者聊天,巧合的CPP.CHAT HOST JON KALB有一个很棒的机会,关于今年的版本及其亮点。

欢迎十月特刊不需要诊断显示搭配Cpp。闲谈,聊天

十月新闻

让你的界面富有表现力的简单方法

这篇文章处理代码可读性的情况,特别是当两个相同类型的参数(< code>赃物)传递给函数或作为模板参数。您经常编写这样的代码吗?您是否经常不小心以错误的顺序传递参数,并破坏代码?本文讨论了几种避免这一问题的方法,具体如下:

  • 在代码本身中表达参数的含义。
  • 在编译时防止错误使用。

建议列表从本机建议开始始终向代码添加注释,然后通过型别名,最后,强大的类型。

不要重新命名空间< code>性病

亚瑟·欧·德怀尔写了博客文章证明用户应该使用限定名称来定义模板专门化,而不是重新打开命名空间< code>性病.可读性和清洁代码是其中的一个原因。一个不太明显的原因是,如果代码放在命名空间内,则名称可以与标准库中的某些内容发生碰撞,这意味着您可能需要限定CURLY括号内的名称。

物品末尾涵盖了一个有趣的案件。样本看起来很典型,但它产生了未定义的行为。它重新打开了命名空间< code>性病并插入专门使用某些用户类型的标准功能的过载。但是,不允许用户添加新的过载功能< code>性病名称空间,所以在这种情况下,坏的实践会导致未定义的行为。

继续回报

为返回值搬了或者复制?本文通过不同的示例提出并讨论了经典的c++问题文章,由菲利普特纳写的。作者不仅讨论了在内存中复制,移动或直接构建的返回值的位置,还显示了分析呼叫图的程序集。

讨论的案件是:

  • 直接在调用者函数提供的内存中构造对象(“unmaterialized价值传递”).
  • 返回局部变量和一个命名为返回值优化.同样,如果通过函数的所有路径都以返回对象结束,编译器可以使用调用者提供的返回值空间,从而避免任何复制或移动。
  • 返回行为不同的函数参数。
  • 从局部变量移动。
  • 类中使用的两种带有隐式转换的类型< code>返回(有趣的是,它是a复制在pre-C + + 14,移动在新标准)。
  • 有一些案例会触发复制, 不是移动

C ++智能指针和阵列

十月,Bartlomiej Filipek在c++ Stories上发表了几篇关于智能指针的新文章。其中一个是献给智能指针和数组.在这篇博文中,他探讨了为数组创建和初始化智能指针的方法。使用来自c++ 20的一个有趣的添加,他使用一组函数来跳过值初始化,以获得更好的性能(函数< code>_for_overwrite后缀)。

本文还对关于是否需要堆栈溢出的讨论进行了很好的总结< code>unique_ptr.有一个数组< code>std::数组和< code>STD ::.比较这些技术的表格可作为实用指南:
指针,阵列和矢量比较
您可以浏览它,并选择对您的情况重要或适用的条件,以获得解决方案。

RECAP用户定义的文字

还有一篇文章是关于更具表现力和可读性的代码的。在他的新博客中,Jonathan Boccara提供了一个复习基础知识如何在c++ 11/14/17中使用用户定义的文字以及如何使用它们。他讨论了各种有用的方面,比如UDL允许的类型,以及一些需要记住的有趣规则(例如,对于以大写字母开头的后缀,原型之间不应该有空格< code>操作符”“,应该存在用户定义后缀的起始下划线)。
c++ 14和c++ 17将udl引入了标准库。的字符串字面值(c++ 14)< code>年代后缀、带有所有时间和日期相关后缀的chrono字面值(c++ 14),以及带有< code>sv后缀在文章中讨论过。

组合字符串和模板。会出什么问题呢?

“stryy模板”是一篇很好的文章,讨论了将字符串作为非类型模板参数传递的最新语言能力。非类型模板形参有一个非常重要的特征——当与相同的模板实参一起使用时,它们会定义相同的特化。模板实参的相等性可能是一个编译时计算,而不仅仅是使用完全相同的实体。在此基础上,c++ 20允许在满足几个条件时使用类类型非类型模板形参,最终使使用字符串作为模板实参成为可能。本文通过< code>fixed_string类型。当给定字符串应该命名有效/注册类型时,它还给出了一个有趣的实际示例。

JetBrains共享CppCon Keynote Recordings

CppCon是c++专家和那些对c++生态系统感兴趣的人一年一度的盛会。它带来了新的提案公告,讨论了各种c++特性的实现细节,并向公众展示了新的工具和技术。经过2年的休息,CppCon ' 21回到常规的个人格式,同时也运行一个混合格式。如果您不能亲自参加会议或在线,JetBrains为您提供了一个机会,以跟上来自c++世界的最热新闻。今年我们成为CppCon YouTube频道的官方赞助商,并编写了一份特殊页面使用CPPCON'21主题演讲会话录制。
Timur Doumler最近以开发者倡导者的身份加入了JetBrains c++团队,他是那些幸运的现场访客之一,并在他的博客中分享了他对这次活动的印象旅行报告

c++工具的发展:静态代码分析器

如果您还不相信静态分析是有帮助的,并且您需要更多的实际示例来帮助您做出决定,请查看本文文章由PVS-Studio团队完成。首先介绍一些来自CovidSim、StarEngine和LLVM项目的有趣例子。在一些不幸的情况下,有一些基本的错误可能会造成伤害。

静态代码分析以及代码检查、测试和消毒剂等技术可以帮助防止此类错误。本文的重点是作者创建的一个特定的分析器,它可以作为各种ide的插件,也可以作为独立的工具。作者展示了它在Poco和其他项目中捕捉到的各种错误。讨论的问题包括内存安全问题、未定义行为的情况和始终为真的代码分支。

最后,本文讨论了各种静态代码分析器以及如何从现有选择中进行选择。它还揭示了假阳性和分析基线的主题。

语言的新闻

和往常一样,这里有一些c++标准化领域的亮点。

标准库模块std和std.all

模块在这里-它们只是不均匀分布(这是一个参考)虽然我们等待工具赶上并给我们一个机会看看他们是否符合他们的承诺,你可能会感到失望的是,标准库本身不能作为模块提供。本文建议使用不是一个但两个标准库模块来解决此问题。导入STD为您提供STD命名空间中的所有标准库,包括从C继承的所有类型和函数。值得注意的是它不是导出全局命名空间中的任何C标识符,即使相应的< code>#include <骗子>可能已经完成了。如果在全局名称空间中存在依赖于这些标识符的现有代码,则导入< code>std.compat是给你的。它导入的标识符与< code>< c>#包括会做。但请注意,这些模块都不导出任何宏。如果您依赖于任何标准库宏,就像< code>断言或者特征测试宏,然后您仍然需要< code>#包括适当的标题。现在需要这么少,这可能是最好的方法,特别是如果我们最终获得合同(以及其他事情,更换< code>断言宏)。说到哪个......

P2461r0 -基于闭包的契约语法

上个月,我提到有一篇尚未发表的新论文,它提出了一种基于lambda捕获语法的契约替代语法。那篇论文现在已经发表了,所以我们可以进一步讨论它。
P2388提出了一种看起来像属性的语法,但由于存在冒号字符和沿着C ++ 20合约行的其他可能的未来扩展,并不严格地属性语法。本文提出(几乎)完全相同语义,但又有所不同语法.这个看起来不像属性,而像lambda !这三个关键词:< code>前,< code>断言,< code>邮政,但是现在它们不在方括号内,后跟一个(n optional) capture列表和一个包含检查代码的花括号内的正文。对于后置条件," lambda "也可以接受一个(可选的)参数-返回值。

起初它看起来像是“看起来的属性 - 但是 - 不是 - 完全属性”问题一直是持久的,但是用lambdas。这是真的,我们今天拥有的Lambdas存在一些分歧:

  1. 捕获列表是可选的。事实上,对于第一个MVP步骤必须省略!对于“Real”Lambdas,捕获列表也用作“Lambda介绍者”,因此即使是空的,也可以在语法上存在。在这种情况下,上下文敏感关键字< code>前,< code>邮政,或< code>断言,注意这个角色,所以可以省略它(在这种情况下,它就像< code>[&]指定)。
  2. 只有后置条件可以接受参数,它只能接受一个参数,它必须对应于返回类型。这是一个额外的限制,我们可以在未来放松,如果有好的理由,所以它不是真正的散度。
  3. 没有返回语句(或者说,它是可选的)。函数体中的条件代码被隐式地计算并“返回”。这实际上是缩写的lambdas.-它们仍然在飞行中-所以这个语法是有变化的。不过,这是缩写lambda的完美候选。
  4. 没有为返回值参数指定对后期后的类型。如在第3页中,这是缩写的lambda语法(尽管其中一个扩展)。它是隐含的< code>汽车&&.

至少有许多优势,这对于我来说,至少,这表明这是一个特别有希望的方向:

  1. 当您查看代码时,您的直觉和lambda语法的先验知识使它很容易理解,即使是使用缩写语法。如果允许使用捕获语法,那么它的含义也应该很明显,特别是在对函数末尾的参数变化进行推理时(尽管这本身也会引发一些问题)。
  2. 对于执行什么以及何时执行,还有一个直观的心理模型。捕获是预先评估的。实体可以在任何时候执行,也可以根本不执行(我们看不到它们的调用,所以我们不应该依赖它们),但即使没有执行,它们也必须执行编译
  3. 对于MVP来说,语法的某些部分受到了过度的限制,但是很容易看出将来语法中会如何处理事情,比如有状态后置条件。
  4. 我们将从lambdas本身的任何进化中获益,比如缩写lambdas和对返回值的解构。
  5. 没有新的“迷你语言”需要学习。
  6. 我们可以使用与合同的属性。
  7. 语义的演进不太可能对当前可预见的演进产生ABI影响。

从积极的方面看,这一建议引起了许多人的兴趣和讨论,许多人非常赞成它。另一方面,如果我们有任何机会能够在c++ 23中获得最小的契约支持,那么这个新的讨论可能已经结束了。

P2445r1 - std:: forward_like

C ++ 11引入了具有RValue参考的移动语义,以及< code>STD :: MOVE.和< code>向前std::与他们一起,帮助我们实现“完美转发”。对于许多开发人员来说,即使是十年之后,这仍然像是一种魔法,但对于库的实施者来说,它们是用干净的界面实现最佳性能的必要工具(即使内部变得有点混乱)。而< code>STD :: MOVE.将一个偏僻的人变成rvalue,< code>向前std::目的是保留它所传递的值类别,但要求非限定类型作为模板实参来这样做。然而,在某些情况下,您还需要考虑的价值类别另一个类型。这在摘要中得到了非常疏远的,但这里的激励用例是推断这一点.如果< code>这个是一个显式,模糊的参数,那么拥有对象的值类别变为通用 - 这是迈出的主要点 - 但这会影响您可能需要转发的成员的价值类别。不幸的是只是抓住了< code>decltype成员的数量是不够的,有几个模型可以说明这些值类别如何与在不同情况下很重要的细微差异交互。理解这些模型的含义并正确地使用它们可能会很棘手,因此在库中拥有这样一个工具将是与explicit一起使用的有用工具< code>这个当我们在c++ 23中得到参数时。

P2012R2 - 修复基于范围的循环,Rev 2

通常我们讨论的是正在进行中的建议,或者已经被采纳到工作草案中。至少就目前而言,这一次是如此拒绝了!但是,有一个强有力的共识,即它试图解决的问题值得寻求解决,所以它可能会回来。是否尚未以类似的形式或具有不同的方法。那么循环范围的问题是什么?

面对它,问题只是悬垂引用的特殊情况。但是在临时寿命延伸之间存在紧张的相互作用,以及基于范围的循环的生成性质,这使得这种情况尤其是有害的。采取以下例子:

for(auto elem:createperson()。getValues()){std :: cout <<“值:”<< elem <<“\ n”;}

现在,如果< code>createPerson ()暂时返回< code>getValues()返回参考临时的参考,我们最终得到悬垂的参考。这可能似乎不是直观的,因为类似的寻找:

if(auto elem = createPerson().getValues()[0]) {std::cout << "value: " << elem << "\n";}

工作由于寿命延长!临时元素的生命周期被延长到创建它的语句的末尾,此时我们已经将元素复制到另一个变量中。看起来对于for循环也是一样的。但实际上,for循环被指定为这个表达式被写成了多个语句。因此,创建临时变量的语句在循环开始之前已经完成,因此已经被销毁!导致问题的主要是(有效的)代码生成步骤。我们不看到语句的分离从分配元素到循环变量的部分中介绍临时的临时。

本文建议通过改变如何指定基于范围的for来解决这个问题,以便扩展范围初始化式中创建的所有临时对象的生存期。这似乎是合理的,但在委员会投票中被否决了。为什么它被拒绝了?如果不引用个人的话,很难说太多,但两种反对意见似乎是主要原因:

  1. 这是一个破坏的变化。论文认为,这是我们在实践中不应该达到的技术性 - 除了已经破坏的代码。一些评论者不同意。
  2. 有一个单独的努力来指定可以以类似的方式延长临时生命周期的方法。这项工作的结果可能会取代该文件的建议或与之相冲突。

希望这将以解决这些问题的方式再次来到。同时,可以使用更好的选择< code>for_each.,已经具有直观的行为,其范围形式为(< code>范围:: for_each.)几乎和语言结构一样简洁。

阿纳斯塔西娅Kazakova

推特:@anastasiak2512

Anastasia是电信和嵌入式系统的C/ c++软件开发人员,参与了家庭网络宽带容量估算的研究,并参与了4G网络的启动。她现在是公司的产品营销经理JetBrains c++工具

菲尔·纳什

推特:@phil_nash

Phil是c++测试框架的原始作者Catch2.作为开发商倡导者SonarSource他参与了SonarQube, SonarLint和SonarCloud,特别是在c++环境下。他也是c++伦敦c++在海上,同时也是《生活大爆炸》的联合主持人和制片人cpp.chat播客。更一般地,菲尔是良好的测试实践,TDD和使用类型系统和功能技术的倡导者,以降低复杂性并提高正确性。他以前在金融和移动工作中工作,并为C ++提供了TDD的培训和辅导。

发现更多的

Baidu