当前位置: 首页 > 科技观察

他来了,他来了,C++17新特性的精髓在这里

时间:2023-03-14 16:03:42 科技观察

本文转载自微信公众号《程序喵大师》,作者程序喵大师。转载本文请联系程序大师喵公众号。程序喵之前介绍过C++11和C++14的新特性(点击对应文字可直接访问),今天就给亲爱的读者们介绍一下C++17的新特性,现在基本上各编译器已经为C++17提供了完整的支持。建议大家在编程中尽量使用C++17,可以在一定程度上简化代码编写,提高编程效率。主要新特性如下:构造函数模板推导结构化绑定If-switch语句初始化内联变量折叠表达式constexprlambda表达式命名空间嵌套__has_include预处理表达式使用*this捕获lambda表达式中的对象复制新增属性字符串转换std::variantstd::optionalstd::anystd::applystd::make_from_tupleas_conststd::string_viewfile_systemstd::shared_mutex下面对程序一一介绍:C++17中构造函数模板推导在构造模板类对象之前,需要指定类型:pairp(1,2.2);//beforec++17C++17不需要特别指定,直接导出类型即可。代码如下:pairp(1,2.2);//c++17自动推导vectorv={1,2,3};//c++17结构化绑定通过结构化绑定,方便获取对应的值对于tuple、map等类型很多,看代码:std::tuplefunc(){returnstd::tuple(1,2.2);}intmain(){auto[i,d]=func();//是C++11平局吗?更高级的cout<m={{0,"a"},{1,"b"},};for(constauto&[i,s]:m){cout<方法。classEntry{public:voidInit(){name_="name";age_=10;}std::stringGetName()const{returnname_;}intGetAge()const{returnage_;}private:std::stringname_;intage_;};模板autoget(constEntry&e){ifconstexpr(I==0)return.GetName();elseifconstexpr(I==1)returne.GetAge();}namespacestd{template<>structuple_size:integral_constant{};template<>structuple_element<0,Entry>{usingtype=std::string;};template<>structuple_element<1,Entry>{usingtype=int;};}intmain(){Entrye;e.Init();auto[name,age]=e;cout<autosum(Ts...ts){return(ts+...);}inta{sum(1,2,3,4,5)};//15std::stringa{"hello"};std::stringb{"world"};cout<)#definehas_charconv1#include#endif#endifstd::optionalConvertToInt(conststd::string&str){intvalue{};#ifdefhas_charconvconstautolast=str.data()+str.size();constautores=std::from_chars(str.data(),last,value);if(res.ec==std::errc{}&&res.ptr==last)returnvalue;#else//alternativeimplementation...其他实现方式#endifreturnstd::nullopt;}在lambda表达式中使用*this捕获一个对象的副本一般情况下,在lambda表达式中访问一个类的对象成员变量需要捕获this,但是这里捕获的是this指针,指向对象的引用。一般情况下可能没问题,但是如果是多线程,函数的作用域超出了对象的作用域,对象已经析构了,访问成员变量,就会出问题。structA{inta;voidfunc(){autof=[this]{cout<intmain(){conststd::stringstr{"123456098"};intvalue=0;constautores=std::from_chars(str.data(),str.data()+4,value);if(res.ec==std::errc()){cout<var;//编译失败}如何避免这种情况,可以使用std::monostate来打桩,模拟一个空状态std::variantvar;//可以编译成功std::optional有时候我们可能会有让函数返回一个对象的需求,如下:structA{};Afunc(){if(flag)returnA();else{//异常情况下,如何返回一个异常值,想返回一个null}}一种方式是返回一个对象指针,异常情况下可以返回nullptr,但是这个涉及到内存管理,可能你会用到智能指针,但实际上还有一种更方便的方法是std::optional。std::optionalStoI(conststd::string&s){try{returnstd::stoi(s);}catch(...){returnstd::nullopt;}}voidfunc(){std::strings{"123"};std::optionalo=StoI(s);if(o){cout<<*o<(a)<(a)<(a)<(std::move(tuple));}std::string_view通常我们传递一个字符串的时候,会触发对象的复制操作,largestring复制赋值操作会触发堆内存分配,极大影响运行效率。有了string_view,就可以避免copy操作,在正常的传输过程中可以传递string_view。voidfunc(std::string_viewstv){cout<