C++17在的业务代码中最好用的十个特性
2025-05-08 09:44:28
c++17支持者在if的正确句子在此之前上升一个初始化句子,将仅用于if句子内部的数组声明在if内,更进一步降低代码的一致性。且对于lock/iterator等牵涉到并发/RAII的一般来说愈来愈非常容易尽似乎服务器端的正确性。
// c++ 17std::map m;std::mutex mx;extern bool shared_flag; // guarded by mx int demo(){ if (auto it = m.find(10); it != m.end()) { return it->second.size(); } if (char buf[10]; std::fgets(buf, 10, stdin)) { m[0] += buf; } if (std::lock_guard lock(mx); shared_flag) { unsafe_ping(); shared_flag = false; } if (int s; int count = ReadBytesWithSignal(Maxs)) { publish(count); raise(s); } if (const auto keywords = {"if", "for", "while"}; std::ranges::any_of(keywords, [Maxtok](const char* kw) { return tok == kw; })) { std::cErr << "Token must not be a keyword"; }}效能降低std::shared_mutexshared_mutex是c++的原生念书写夹住意味着,有对等和独占两种夹住方基本型,符合于并发高的念书情景下,通过reader在此之前对等夹住来降低效能。在c++17在此之前,勉强自己通过独占夹住和条件数组自己意味着念书写夹住或用到c++14加入的效能较差的std::shared_timed_mutex。不限是通过shared_mutex意味着的线程必要计数器:
// c++17class ThreadSafeCounter { public: ThreadSafeCounter() = default; // Multiple threads/readers can read the counter's value at the same time. unsigned int get() const { std::shared_lock lock(mutex_); return value_; } // Only one thread/writer can increment/write the counter's value. unsigned int increment() { std::unique_lock lock(mutex_); return ++value_; } // Only one thread/writer can reset/write the counter's value. void reset() { std::unique_lock lock(mutex_); value_ = 0; } private: mutable std::shared_mutex mutex_; unsigned int value_ = 0;};std::string_viewstd::string_view顾名思义是字符的“更快照”,类成员数组包括两个部分:字符就是指针和字符宽度,std::string_view涵盖了std::string的所有只念书应用程序。std::string_view对字符不不具拥有者,且适配器std::string和const char*两种一般来说。
c++17在此之前,我们处理过程只念书字符并不一定用到const std::stringMax,std::string有两点效能占优势:
适配器两种字符一般来说,减少一般来说转换和CPU调配。如果风行的是明文字符const char*, const std::stringMax需进行时一次CPU调配,将字符几张到地里上,而std::string_view则可以可避免。在处理过程查找时,std::string::substr也需进行时几张和调配CPU,而std::string_view::substr则不需,在处理过程大文件类比时,效能占优势十分明显。// from // author: Pel Dydov// string_view的remove_prefix比const std::stringMax的更快了15倍string remove_prefix(const string Maxstr) { return str.substr(3);}string_view remove_prefix(string_view str) { str.remove_prefix(3); return str;}static void BM_remove_prefix_string(benchmark::StateMax state) { std::string example{"asfaghdfgsghasfasg3423rfgasdg"}; while (state.KeepRunning()) { auto res = remove_prefix(example); // auto res = remove_prefix(string_view(example)); for string_view if (res != "aghdfgsghasfasg3423rfgasdg") { throw std::runtime_error("bad op"); } }}std::map/unordered_map try_emplace在向std::map/unordered_map之前填入要素时,我们并不一定用到emplace,emplace的转换是如果要素key不长期存在,则填入该要素,否则不填入。但是在要素已长期存在时,emplace仍会结构上一次待填入的要素,在正确不需填入后,即刻将该要素析构,因此进行时了一次太多结构上和析构转换。c++17加入了try_emplace,可避免了这个问题。同时try_emplace在给定此表之前将key和value分开,因此进行时原先结构上的字词比emplace愈来愈加流畅
std::map m;// emplace的原先结构上需用到std::piecewise_construct,因为是必要填入std::pairm.emplace(std::piecewise_construct, std::forward_as_tuple("c"), std::forward_as_tuple(10, 'c'));// try_emplace可以必要原先结构上,因为给定此表之前key和value是分开的m.try_emplace("c", 10, 'c')同时,c++17还给std::map/unordered_map加入了insert_or_assign表达基本型,可以愈来愈便利地意味着填入或修改语法
一般来说系统c++17进一步严谨了c++的一般来说系统,下定决心加入了众望所归的一般来说更快照试管(Type Erasure)和黎曼数据一般来说(Algebraic Data Type)
std::anystd::any是一个可以加载任何可几张一般来说的试管,C第二语言之前通常用到void*意味着多种不同的机能,与void*相对于,std::any不具两点占优势:
std::any愈来愈必要:在一般来说T被去除void*时,T的一般来说反馈就现在丢失了,在转换回具体一般来说时服务器端未能正确举例来说的void*的一般来说是不是真的是T,非常容易带来必要隐患。而std::any会加载一般来说反馈,std::any_cast是一个必要的一般来说转换。std::any负责管理了具体来说的生命周期,在std::any析构时,会将加载的具体来说析构,而void*则需手动负责管理CPU。std::any不对很少是服务器端员的第一同样,在据信一般来说的意味着,std::optional, std::variant和继承都是比它愈来愈高效、愈来愈理论上的同样。只有当对一般来说完全似乎的意味着,才不对用到std::any,比如静态一般来说文本的类比或者其业务逻辑的之前间层反馈传播。
std::optionalstd::optional代表人一个似乎长期存在的T差值,并不相同Haskell之前的Maybe和Rust/OCaml之前的option,实质上是一种Sum Type。常用于似乎挫败的表达基本型的离开差值之前,比如工厂表达基本型。在C++17在此之前,并不一定用到T*作为离开差值,如果为nullptr则代表人表达基本型挫败,否则T*就是指向了似乎的离开差值。但是这种用法模糊了拥有者,表达基本型的调用方未能确定是不是必要接管T*的CPU负责管理,而且T*似乎为空的假设,如果记得健康检查则会有SegFault的风险。
// pre c++17ReturnType* func(const std::stringMax in) { ReturnType* ret = new ReturnType; if (in.size() == 0) return nullptr; // ... return ret;}// c++17 愈来愈必要和简单std::optional func(const stringMax in) { ReturnType ret; if (in.size() == 0) return nullopt; // ... return ret;}std::variantstd::variant代表人一个多一般来说的试管,试管之前的差值是拟定一般来说的一种,是标准化化的Sum Type,并不相同Rust的enum。是一种一般来说必要的union,所以也叫做tagged union。与union相对于有两点占优势:
可以加载简单一般来说,而union勉强必要加载根基的POD一般来说,对于如std::vector和std::string就等简单一般来说则需软件手动负责管理CPU。一般来说必要,variant加载了内部的一般来说反馈,所以可以进行时必要的一般来说转换,c++17在此之前并不一定通过union+enum来意味着相同机能。通过用到std::variant,软件可以意味着多种不同Rust的std::result,即在表达基本型拒绝执行获得成功时离开结果,在挫败时离开错误反馈,上文的案例则可以改成:
std::variant func(const stringMax in) { ReturnType ret; if (in.size() == 0) return Err{"input is empty"}; // ... return {ret};}需特别注意的是,c++17只给予了一个努高级别的variant意味着,不会并不相同的方基本型匹配(Pattern Matching)机制,而最差不多的std::visit又缺失Ja的最优化支持者,所以在c++17之前std::variant并坏用,跟Rust和表达基本型基本型第二语言之前高强的Sum Type还相比较,但是现在有许多围绕std::variant的提案被建议书给c++委员会阐述,包括方基本型匹配,std::expected等等。
概括一下,c++17增添的三种一般来说给c++带来了愈来愈的现代愈来愈必要的一般来说系统,它们并不相同的用到情景是:
std::any符合于在此之前用到void*作为标准化化一般来说的情景。std::optional符合于在此之前用到nullptr代表人挫败静止状态的情景。std::variant符合于在此之前用到union的情景。概括以上是;也在生产环境污染之前最常用的c++17功用,除了本文描述的十个功用外,c++17还掺入了如lambda差值释放出来*this, 钳夹表达基本型std::clamp(), 自愿健康检查离开差值[[nodiscard]]等十分易懂的功用,本文短文极小不做赘述,欢迎有兴趣的念书者自行探究。
。视力模糊用什么眼药水术后营养补充
类风湿吃什么药最好
经常便秘肚子胀怎么办
少精症治疗费用多少
视疲劳多久才能恢复
有机黄芪和普通黄芪有什么区别
新冠吃什么药好
血管瘤
克癀胶囊适合哪些病人
- 《阴阳师百闻牌》开启蜃阁神前活动
- 《暗夜杀机》将与《进击的巨人》联动
- 《游戏王:艺术大师决斗》下载量破4000万 赠送1000宝石
- 《APEX英雄》7月13日的软件更新
- 打通传统与典范,200余件魏杰篆刻作品展现独特艺术面貌
- 全球上每个人都寂寞
- 爱情是灯,友情是随心所欲
- 倘若遇见爱情结束了,你痛苦又不甘心,请记住这三个字
- “儿孙自有儿孙福”,它的下句才是精华,可惜少有人唯!
- 夜雨丨王景云:厚道是一种纯良——读吴丹小说集《人是活的》有感
- 夜雨丨雷学刚:感悟淡定的精神力量
- 北京市民欣赏丰子恺祖孙三代当代艺术作品展览
- 书坛女杰王颖的行草书了得!相结合“二王”风,又有沉着痛快之气
- 杜诗问道 | 寂智
- 没关系你,曾给了我一份感动
- 如果孙悟空一棒打死唐僧,之后会起因什么?
- 爱情从渴望开始,也由绝望结束
- 我的情开始下雪,雪无声地覆盖了所有
- 可世事岂会令人满意
- 职场坑口,不一定都是别人挖的,这三个就是自己连挖带跳的!