日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C++17特性一览

發(fā)布時(shí)間:2024/4/18 c/c++ 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++17特性一览 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

引言

再說(shuō)回C++17,這次的更新比C++14要大不少,其中很多東西都可以為我們的C++代碼在優(yōu)化代碼可讀性的同時(shí)提高效率,我們一起來(lái)看看吧

構(gòu)造函數(shù)模板推導(dǎo)

其實(shí)我更愿意叫它模板類型自動(dòng)推導(dǎo),代碼展示大概就是這樣:

vector items = {1,2,3};// pair pa(4, "string"); 不直接匹配字符串pair pa(4, string("hihi"));cout << pa.second << " " << items[2] << endl;輸出:hihi 3

結(jié)構(gòu)化綁定

可以綁定pair,tuple,數(shù)組,結(jié)構(gòu)體,結(jié)構(gòu)化綁定以后也可以修改原值,也可以使自定義類型支持結(jié)構(gòu)化綁定,但是要修改std,感覺沒(méi)什么必要。

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當(dāng)然不能使用結(jié)構(gòu)化綁定啦

if-switch語(yǔ)句初始化

變量的作用域劃分的更明顯了。

if (int a = 29; a < 101) {cout << a; }

聯(lián)變量

這是個(gè)非常有意思的東西,你可能會(huì)覺得函數(shù)inline可以提高效率,變量inline有什么用?這其實(shí)涉及到inline的一個(gè)一般不廣為人所知的特性,即多個(gè)翻譯單元內(nèi)的重復(fù)聲明C++鏈接器只選擇一個(gè),這意味這有inline聲明的函數(shù)和變量我們可以聲明在頭文件中了

代碼來(lái)看就是這樣:

// 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 內(nèi)聯(lián)變量 c++17》
《GCC,Clang 在C模式,較低優(yōu)化等級(jí)下,鏈接器對(duì)內(nèi)聯(lián)函數(shù)報(bào)未定義錯(cuò)誤,為什么?》

折疊表達(dá)式

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...); }

體的細(xì)節(jié)可查看這篇文章《C++17 fold expression》

constexpr lambda表達(dá)式

需要注意的是有如下約束:函數(shù)體不能包含匯編語(yǔ)句、goto語(yǔ)句、label、try塊、靜態(tài)變量、線程局部存儲(chǔ)、沒(méi)有初始化的普通變量,不能動(dòng)態(tài)分配內(nèi)存,不能有new delete等,不能使用虛函數(shù)

constexpr auto lamb = [](auto b) {int ret = 0; // C++14中放寬了lambda的標(biāo)準(zhǔn)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(); }

語(yǔ)法糖,更方便更舒適

from_chars函數(shù)和to_chars

具體可參考《C++標(biāo)準(zhǔn)庫(kù)里自帶的數(shù)值類型和字符串互相轉(zhuǎn)換函數(shù)》

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以后的最后一個(gè)迭代器 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

千盼萬(wàn)盼你終于是來(lái)了。。這個(gè)不需要解釋了,就是讀寫鎖了。

關(guān)于與mutex的性能對(duì)比可以看這里《std::shared_mutex和std::mutex的性能對(duì)比(benchmark)》

具體內(nèi)容可參考:《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,第一個(gè)參數(shù)必須擁有默認(rèn)構(gòu)造函數(shù)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; 第一個(gè)參數(shù)沒(méi)有構(gòu)造函數(shù) 編譯失敗 // std::monostate就是防止全部的參數(shù)都沒(méi)有默認(rèn)構(gòu)造函數(shù) std::variant<std::monostate, NoDefConstr_seven, int> v2;輸出: 1 0 hello

std::optional

具體可參考《C++干貨系列——C++17新特性之std::optional》

其實(shí)就是為了防止我們平時(shí)在代碼中返回一個(gè)不存在語(yǔ)義時(shí)隨便設(shè)置的magic number。

std::any

一般頂多variant就足夠用了,何必用Any呢 但在極端情況下,用any總比用void*強(qiáng)得多,鼓勵(lì)實(shí)現(xiàn)避免小對(duì)象的動(dòng)態(tài)分配

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"); // 這個(gè)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

我認(rèn)為其實(shí)就是把容器的值當(dāng)做函數(shù)的輸入

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應(yīng)用可變參數(shù)函數(shù)(Applying a variadic function with std::apply)》

std::make_from_tuple

使用make_from_tuple可以將tuple展開作為構(gòu)造函數(shù)參數(shù):

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

平時(shí)代碼中可以大規(guī)模使用的一個(gè)特性。其實(shí)對(duì)于string的爭(zhēng)論一直沒(méi)有停止過(guò),很多人認(rèn)為string是字節(jié)串而不是字符串,因?yàn)閟tring是可以改變的,這一切爭(zhēng)論到C++17可以停止了。string_view的substr與構(gòu)造時(shí)間復(fù)雜度為O(1),且不會(huì)產(chǎn)生拷貝,因?yàn)閟ubstr只是一個(gè)指針操作。

可以參考如下兩篇文章:
《C++17,使用 string_view 來(lái)避免復(fù)制》
《C++17 string_view的高效以及陷阱》

std::file_system

具體可參考《c++ filesystem》

這其實(shí)模子是boost的file_system,最早2003年就出來(lái)了,因?yàn)槭强缙脚_(tái)的,所以可以說(shuō)是非常舒服了。

有一說(shuō)一,在我的機(jī)子上跑不了這個(gè)。

代碼:

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)

并行算法庫(kù)

這可以說(shuō)是C++17最重要的幾個(gè)特性之一,這個(gè)特性為幾乎所有標(biāo)準(zhǔn)庫(kù)函數(shù)加上一個(gè)執(zhí)行策略參數(shù),可以讓使用者選擇并行還是串行,這不僅包括七個(gè)新的算法,還有我們熟知的sort等。

具體可參考:
《[譯]C++17,標(biāo)準(zhǔn)庫(kù)新引入的并行算法?》
《STL并行算法庫(kù)》

constexpr if

在C++17以前泛型函數(shù)中是不可以出現(xiàn)if這樣的邏輯判斷符的

template <int N, int... Ns> auto sum() {if (sizeof...(Ns) == 0) // 若參數(shù)包為空, 直接返回 Nreturn N;else // 否則進(jìn)行遞歸調(diào)用return N + sum<Ns...>(); }

這樣就會(huì)編譯失敗。

以前的做法是用模板遞歸,就像這樣:

// 只有一個(gè)模板參數(shù)時(shí)調(diào)用此模板 template<int N> int sum() {return N; }// 模板參數(shù) > 2 個(gè)時(shí)調(diào)用此模板 template <int N, int N2, int... Ns> int sum() {return N + sum<N2, Ns...>(); }

現(xiàn)在我們可以這樣:

template <int N, int... Ns> auto sum() {if constexpr (0 == sizeof...(Ns))return N;elsereturn N + sum<Ns...>(); }

具體可參考:《C++17 之 “constexpr if”》

總結(jié)

以上是生活随笔為你收集整理的C++17特性一览的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。