C++17特性一览(转载)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43705457/article/details/108903962
引言
这一系列的第二篇文章。但是其实我并不想写第三篇,也就是描述C++20的特性了,现在这个时间点GCC最新的版本就是10.2,安装以后发现还是没有办法编译C++20,也可能是我的方法不太对,但是确实是让人非常的烦,写不了代码介绍它作甚?况且,反正未来五六年内各大公司也不会上线C++20吧。
再说回C++17,这次的更新比C++14要大不少,其中很多东西都可以为我们的C++代码在优化代码可读性的同时提高效率,我们一起来看看吧
构造函数模板推导
其实我更愿意叫它模板类型自动推导,代码展示大概就是这样:
vector items = {1,2,3};// pair pa(4, "string"); 不直接匹配字符串pair pa(4, string("hihi"));cout << pa.second << " " << items[2] << endl;输出:hihi 3
结构化绑定
可以绑定pair,tuple,数组,结构体,结构化绑定以后也可以修改原值,也可以使自定义类型支持结构化绑定,但是要修改std,感觉没什么必要。
std::tuple<int, double> func_two() {return std::tuple(1, 2.2);
}auto[i, d] = func_two();
cout << i << " " << d << endl;map<int, string> mp = {{0, "a"},{1, "b"},
};for(const auto& [x, y] : mp){cout << x << " " << y << endl;
}pair pa(4, string("hihi"));
auto&[x, y] = pa;
cout << x << " " << y << endl;输出:
1 2.2
0 a
1 b
4 hihi/*
vector vec = {1,2,3};
auto&[xx, yy, zz] = vec;
cout << xx << endl;
*/ vector当然不能使用结构化绑定啦
if-switch语句初始化
变量的作用域划分的更明显了。
if (int a = 29; a < 101) {cout << a;
}
内联变量
这是个非常有意思的东西,你可能会觉得函数inline可以提高效率,变量inline有什么用?这其实涉及到inline的一个一般不广为人所知的特性,即多个翻译单元内的重复声明C++链接器只选择一个,这意味这有inline声明的函数和变量我们可以声明在头文件中了
代码来看就是这样:
// header file
struct A {static const int value;
};
inline int const A::value = 10;// ==========或者========
struct A {inline static const int value = 10;
}
有兴趣的朋友可以看看下面两篇文章:
《c++ inline variable 内联变量 c++17》
《GCC,Clang 在C模式,较低优化等级下,链接器对内联函数报未定义错误,为什么?》
折叠表达式
template <typename ... TT>
constexpr auto foldSumRec(T... arg) {return (arg + ...);
}
C++17以前得写成这样:
template<typename T>
auto foldSumRec (T arg)
{return arg;
}template<typename T1, typename... Ts>
auto foldSumRec (T1 arg1, Ts... otherArgs)
{return arg1 + foldSumRec(otherArgs...);
}
具体的细节可查看这篇文章《C++17 fold expression》
constexpr lambda表达式
需要注意的是有如下约束:函数体不能包含汇编语句、goto语句、label、try块、静态变量、线程局部存储、没有初始化的普通变量,不能动态分配内存,不能有new delete等,不能使用虚函数
constexpr auto lamb = [](auto b) {int ret = 0; // C++14中放宽了lambda的标准for (size_t i = 0; i < b; i++){ret += i;}return ret;};
namespace嵌套
namespace A {namespace B {namespace C {void func();}}
}// c++17
namespace A::B::C {void func();
}
语法糖,更方便更舒适
from_chars函数和to_chars
具体可参考《C++标准库里自带的数值类型和字符串互相转换函数》
std::array<char, 3> str{"42"};
int result;
std::from_chars( str.data(), str.data()+str.size(),result );
std::cout << result << std::endl;// p是填充到str以后的最后一个迭代器
if(auto [p, ec] = std::to_chars(str.data(), str.data() + str.size(), 425);ec == std::errc()){if(p == str.end()){std::cout << "hello world\n";}std::cout << std::string_view(str.data(), p - str.data());
}
输出:
42
hello world
425
std::shared_mutex
千盼万盼你终于是来了。。这个不需要解释了,就是读写锁了。
关于与mutex的性能对比可以看这里《std::shared_mutex和std::mutex的性能对比(benchmark)》
具体内容可参考:《C++ std::shared_mutex读写锁》
std::variant
具体可参考《C++17之std::variant》
struct NoDefConstr_seven{NoDefConstr_seven(int i){std::cout << "NoDefConstr::NoDefConstr(int) called\n";}
};
// variant类似于union,第一个参数必须拥有默认构造函数std::variant<int, std::string> var{"hi"}; // initialized with string alternative
std::cout << var.index() << std::endl; // prints 1
var = 42; // now holds int alternative
std::cout << var.index() << std::endl; // prints 0
try {std::string s = std::get<std::string>(var); // access by typeint i = std::get<0>(var); // access by index
}
catch (const std::bad_variant_access& e) { // in case a wrong type/index is usedstd::cout << "hello\n";
}// std::variant<NoDefConstr_seven, int> v1; 第一个参数没有构造函数 编译失败
// std::monostate就是防止全部的参数都没有默认构造函数
std::variant<std::monostate, NoDefConstr_seven, int> v2;输出:
1
0
hello
std::optional
具体可参考《C++干货系列——C++17新特性之std::optional》
其实就是为了防止我们平时在代码中返回一个不存在语义时随便设置的magic number。
std::any
一般顶多variant就足够用了,何必用Any呢 但在极端情况下,用any总比用void*强得多,鼓励实现避免小对象的动态分配
std::any a = 1;
cout << a.type().name() << " " << std::any_cast<int>(a) << endl;
a = 2.2f;
cout << a.type().name() << " " << std::any_cast<float>(a) << endl;
if (a.has_value()) {cout << a.type().name() << std::endl;
}
a.reset();
// 可以这样判断类型
// assert(a1.type() == typeid(int));
if (a.has_value()) {cout << a.type().name() << std::endl;
}
a = std::string("a");
// 这个string的类型名是真的恶心
cout << a.type().name() << ": " << std::any_cast<std::string>(a) << endl;输出:
i 1
f 2.2
f
NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE: a
具体可查看这篇文章《C++17之std::any》
std::apply
我认为其实就是把容器的值当做函数的输入
int add_ten(int first, int second) { return first + second; }
auto add_ten_lambda = [](auto first, auto second) { return first + second; };std::cout << std::apply(add_ten, std::pair(1, 2)) << '\n';
//std::cout << add(std::pair(1, 2)) << "\n"; // error
std::cout << std::apply(add_ten_lambda, std::tuple(2.2f, 3.0f)) << '\n';输出:
3
5.2
具体可参考《使用std :: apply应用可变参数函数(Applying a variadic function with std::apply)》
std::make_from_tuple
使用make_from_tuple可以将tuple展开作为构造函数参数:
struct Foo {Foo(int first, float second, int third) {std::cout << first << ", " << second << ", " << third << "\n";}
};
int main() {auto tuple = std::make_tuple(42, 3.14f, 0);std::make_from_tuple<Foo>(std::move(tuple));
}
std::string_view
平时代码中可以大规模使用的一个特性。其实对于string的争论一直没有停止过,很多人认为string是字节串而不是字符串,因为string是可以改变的,这一切争论到C++17可以停止了。string_view的substr与构造时间复杂度为O(1),且不会产生拷贝,因为substr只是一个指针操作。
可以参考如下两篇文章:
《C++17,使用 string_view 来避免复制》
《C++17 string_view的高效以及陷阱》
std::file_system
具体可参考《c++ filesystem》
这其实模子是boost的file_system,最早2003年就出来了,因为是跨平台的,所以可以说是非常舒服了。
有一说一,在我的机子上跑不了这个。
代码:
namespace fs = std::filesystem;
fs::path pathToShow("/home/lzl/Desktop/execise");
cout << "exists() = " << fs::exists(pathToShow) << "\n"
<< "root_name() = " << pathToShow.root_name() << "\n"
<< "root_path() = " << pathToShow.root_path() << "\n";
跑完以后显示这样:
./a.out: /lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.26' not found (required by ./a.out)
并行算法库
这可以说是C++17最重要的几个特性之一,这个特性为几乎所有标准库函数加上一个执行策略参数,可以让使用者选择并行还是串行,这不仅包括七个新的算法,还有我们熟知的sort等。
具体可参考:
《[译]C++17,标准库新引入的并行算法 》
《STL并行算法库》
constexpr if
在C++17以前泛型函数中是不可以出现if这样的逻辑判断符的
template <int N, int... Ns>
auto sum()
{if (sizeof...(Ns) == 0) // 若参数包为空, 直接返回 Nreturn N;else // 否则进行递归调用return N + sum<Ns...>();
}
这样就会编译失败。
以前的做法是用模板递归,就像这样:
// 只有一个模板参数时调用此模板
template<int N>
int sum()
{return N;
}// 模板参数 > 2 个时调用此模板
template <int N, int N2, int... Ns>
int sum()
{return N + sum<N2, Ns...>();
}
现在我们可以这样:
template <int N, int... Ns>
auto sum()
{if constexpr (0 == sizeof...(Ns))return N;elsereturn N + sum<Ns...>();
}
具体可参考:《C++17 之 “constexpr if”》
参考:
- 维基《https://baike.tw.lvfukeji.com/wiki/C%2B%2B17》
C++17特性一览(转载)相关推荐
- Java8-19新特性一览 ,认识全新的前沿技术
文章目录 Java8-19新特性一览 ,认识全新的前沿技术 前言 你的收获 Java发展趋势 准备工作 新特性 1.接口private 1).说明 2).案例 3).注意 2.类型推断 1).说明 2 ...
- Apache Ignite(二):核心特性一览(V1.4.0版本)
为什么80%的码农都做不了架构师?>>> 1.数据网格 Ignite内存数据网格是一个内存内的键值存储,他可以在分布式集群的内存内缓存数据. 它通过强语义的数据位置和关系数据路 ...
- Java 9 - 17 特性解读:Java 13
Java 13在2019年9月发布,这个版本引入的正式可用特性几乎没有,是我认为最无聊的版本之一.所以我们跳过Java 13直接来看Java 14吧. Switch表达式 我觉得switch表达式在日 ...
- 4.6 W 字总结!Java 11—Java 17特性详解
作者 | 民工哥技术之路 来源 | https://mp.weixin.qq.com/s/SVleHYFQeePNT7q67UoL4Q Java 11 特性详解 基于嵌套的访问控制 与 Java 语言 ...
- VS2010-2015对C++11/14/17特性的支持
VS2010-2015对C++11/14/17特性的支持 C++11 功能列表 Visual C++ 实现了 C++11 核心语言规范 中的绝大多数功能.许多 C++14 库功能和某些为 C++17 ...
- 【机器学习】scikit-learn 1.0 版本重要新特性一览
1 简介 就在几天前,著名的机器学习框架scikit-learn在pypi上释放了其1.0rc1版本,这里给大家科普一下,版本号中的rc是Release Candidate的简称,代表当前的版本是一个 ...
- 深入解析 | Oracle Database 20c 十大新特性一览
在2020年2月14日,Oracle 正式宣布在 Oracle Cloud 发布 Database 20c 的预览版,同时发布了所有的官方文档. 为了和大家及时分享关于 Oracle 20c 引人瞩目 ...
- 全新 Phaser 3 游戏引擎特性一览
什么是 Phaser ? Phaser 是一款快速.免费以及开源 HTML5 游戏框架,它支持 WebGL 和 Canvas 两种渲染模式,可以在任何 Web 浏览器环境下运行,游戏可以通过第三方工具 ...
- c# 4.0(vs2010)新特性一览
终于静下心来仔细听了一遍Anders Hejlsberg(Visual Studio组的TECHNICAL FELLOW,C#的设计者之一)在PDC08上讲的"The Future of C ...
- Java 9 - 17 特性解读:Java 11
Java 11是自Java 8以来的又一个LTS版本,是目前全球使用最多的LTS版本之一.今天我们接着在Java 9 到 Java 17系列文章中来认识针对普通开发者的Java 11. 字符串API增 ...
最新文章
- 金额阿拉伯数字转换为中文大写
- R语言ggplot2可视化分面图使用facet_wrap函数和facet_grid函数实战
- Java IO 之 InputStream源码
- gpio复用 海思_实现海思平台GPIO驱动
- Android之popWindows底部弹出挡住了华为虚拟键盘问题
- jzoj4248-n染色【数学,快速幂】
- [Leedcode][JAVA][第76题][最小覆盖子串]滑动窗口]
- OUTLOOK2019 解决 无法验证您连接到的服务器使用的安全证书
- UVA 1349 Optimal Bus Route Design (二分图最小权完美匹配)
- 顺风车Android性能优化之View布局优化
- 详解MessageBox(),MsgBox函数的正确使用
- mint-UI上拉加载下拉刷新和fastclick冲突问题解决
- vue-pdf 通过文件流预览pdf文件
- 笔记本电脑触摸板手势命令
- Python基础(编码格式、文件、目录)
- Python代码画喜羊羊怎么画_卧槽!没想到,用Python竟能做五仁月饼
- linux分屏显示命令文件夹,Linux简易命令整理
- python撩妹技能_干货必看 | 手把手教你用Python撩妹
- ahk写入excel单元格_输出excel数据到GUI 获取excel所有Sheet及字段 Autohotkey
- AVS, 主动突围还是坐等救援?
热门文章
- SQL Server 动态行转列(参数化表名、分组列、行转列字段、字段值)
- 基于Windows NBL配置WebInterface
- iOS开发中的HTML解析
- Deploy a replica set
- winform 右下角弹出小窗口
- 3.Prometheus 监控技术与实践 --- Exporter
- 10.Kong入门与实战 基于Nginx和OpenResty的云原生微服务网关 --- 内置插件
- 35.Linux/Unix 系统编程手册(下) -- 进程的优先级和调度
- 12.go 源码文件
- 2. Zend_Controller 快速入门