当前位置: 首页 > news >正文

C++17新语法之if和switch语句中可以初始化变量啦

文章目录

  • 前言
  • if 语句本来的样子
  • if 语句新能力
  • 似曾相识在go中
  • 关于语言的思考
  • 总结

前言

今天在看一些c++代码时偶然间发现一些示例,在if语句的小括号内居然出现了分号,难道这一段是伪代码吗?之前从来没见过这种写法,然后用写了一个例子,用最新的编译器编译后发现真的是正常的代码,并且可以成功运行,然后脑袋有个声音一闪而过,是不是一直就支持这种写法,只是我不知道而已,后来几经周折,终于发现真相,原来这其实是C++17新的语法。

if 语句本来的样子

C++17之前 if 语句的小括号内只能放判断逻辑,if (condition) { /* ... */ } 也就是这样,所以如果想使用一个变量进行判断,那么这个变量必须在if语句之前进行定义,比如我们常常使用的查找map元素的逻辑:

{
    auto it = mp.find("key");
    if (it != mp.end())
        return it->second;
    else
        return defaultValue;
}

if 语句新能力

从C++17开始,if 语句的小括号之中也可以初始化变量了,语法为 if (initializer; condition) { /* ... */ },这样做的好处就是可以更加精细的控制变量的作用域,使代码看起来更加紧凑,比如上面的例子可以改写为:

{
    if (auto it = mp.find("key"); it != mp.end())
        return it->second;
    else
        return defaultValue;
}

最直观的感受就是少了一行代码,但是更重要的特点还是他把变量 it 的作用域限制在了 if 语句之内。

另外就是能一定程度上解决代码缩进层数太多的问题,这也是实际开发过程中遇到的问题,比如下面这段代码:

{
    auto it = mp.find("key");
    if (it != mp.end())
        return it->second;
    else
    {
        int cfg = GetConfig();
        if (cfg)
            return defaultValue1;
        else
            return defaultValue2;
    }
}

在C++17之前的代码中,因为 if 语句中不能包含初始化变量的逻辑,所以会造成 if 嵌套层层递进,当这种条件太多时,缩进层数太多导致代码可读性变差,使用C++17的语法再改进一下就变成了下面这样,逻辑更加清晰了:

{
    if (auto it = mp.find("key"); it != mp.end())
        return it->second;
    else if (int cfg = GetConfig(); cfg)
        return defaultValue1;
    else
        return defaultValue2;
}

switch 语句也是相同的能力扩展,就不再展开说了,这里贴一个 cppreference - switch 上的例子:

{
    struct Device
    {
        enum State { SLEEP, READY, BAD };
        auto state() const { return m_state; }

        /*...*/

    private:
        State m_state{};
    };

    switch (auto dev = Device{}; dev.state())
    {
        case Device::SLEEP:
            /*...*/
            break;
        case Device::READY:
            /*...*/
            break;
        case Device::BAD:
            /*...*/
            break;
    }
}

似曾相识在go中

这个在if中既初始化又进行判断的语法,之前在go中也用过,类似的需求在go中的写法是:

func xxx() {
    if value := mp["key"]; value != nil {
        return value
    } else {
        return defaultValue
    }
}

是不是很像?其实在golang中更规范的用法是使用map查找的第二个返回值来判断元素是否存在,就像下面这样:

func xxx() {
    if value, ok := mp["key"]; ok {
        return value
    } else {
        return defaultValue
    }
}

关于语言的思考

看到上面这种golang和c++17的对比,会发现语言之间都在相互促进,这些所谓的高级语言,总能在其中一种语言中发现另一种语言的影子,也就是说在某些方面上他们是“趋同”的,可能在不久的将来会出现一种“超高级语言”,类似于C++模板机制,C++GolangPython 这些语言作为一种类型,传递到超高级语言之中,编写或者描述完功能逻辑后,自动生成对应语言的代码:

SuperLanguageTemplate<C++/Golang/Python>
[AutoGenerateByFollowingDescription]
{
    / * ... * /
}

总结

  • ifswitch 语句都可以在逻辑判断前初始化变量,变量的定义域可以更精细的控制
  • 编程语言之间相互“借鉴”,部分语法长得越来越像,最后不知道会不会归于统一

==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==

人生并不是不断失去,反过来看,其实人生应该是不断拥有,1秒,2秒,3秒,这些本就不一定属于你的时间,作为馈赠出现在了你的生命里~

相关文章:

  • C++11中的noexcept说明符和操作符
  • 偶然在github开源项目中发现了.travis.yml这货
  • C++17使用std::optional表示一个可能存在的值
  • 推荐一个C++枚举转字符串的开源项目magic_enum
  • 只问耕耘,不问收获,其实收获却在耕耘中
  • 一个月黑风高的夜晚紧急完成gitlab服务器数据迁移
  • SVN如何删除文件名包含空格的文件
  • std::uniform_real_distribution的一个bug引发的服务器崩溃
  • 参考开源项目实现一个简易的C++枚举转字符串的函数
  • git查看历史记录及修改内容
  • rm -rf 真是删库跑路的一把好手
  • 智能指针(三):weak_ptr浅析
  • float的精度和取值范围
  • linux环境下常用的打包、压缩、解压命令(tar、gzip、bzip2、zip)
  • MySQL数据库导入、导出、复制表、重命名表
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • #Java异常处理
  • Date型的使用
  • js算法-归并排序(merge_sort)
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • Sass Day-01
  • 百度地图API标注+时间轴组件
  • 从0实现一个tiny react(三)生命周期
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 如何实现 font-size 的响应式
  • 十年未变!安全,谁之责?(下)
  • 手机端车牌号码键盘的vue组件
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 温故知新之javascript面向对象
  • 学习使用ExpressJS 4.0中的新Router
  • 一些关于Rust在2019年的思考
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • mysql面试题分组并合并列
  • #define
  • #includecmath
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (二)斐波那契Fabonacci函数
  • (转)机器学习的数学基础(1)--Dirichlet分布
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NET 依赖注入和配置系统
  • .NET成年了,然后呢?
  • .NET的微型Web框架 Nancy
  • .NET下ASPX编程的几个小问题
  • .project文件
  • ::什么意思
  • @DataRedisTest测试redis从未如此丝滑
  • [C#]winform利用seetaface6实现C#人脸检测活体检测口罩检测年龄预测性别判断眼睛状态检测
  • [C语言]一维数组二维数组的大小