www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 公眾號精選 > 程序喵大人
[導讀]程序喵之前已經(jīng)介紹過C++11的新特性和C++14的新特性(點擊對應文字,直接訪問),今天向親愛的讀者們介紹下C++17的新特性,現(xiàn)在基本上各個編譯器對C++17都已經(jīng)提供完備的支持,建議大家編程中嘗試使用下C++17,可以一定程度上簡化代碼編寫,提高編程效率。 主


程序喵之前已經(jīng)介紹過C++11的新特性" tab="innerlink" data-linktype="2" rel="nofollow">C++11的新特性和C++14的新特性(點擊對應文字,直接訪問),今天向親愛的讀者們介紹下C++17的新特性,現(xiàn)在基本上各個編譯器對C++17都已經(jīng)提供完備的支持,建議大家編程中嘗試使用下C++17,可以一定程度上簡化代碼編寫,提高編程效率。

主要新特性如下:

  • 構(gòu)造函數(shù)模板推導

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

  • if-switch語句初始化

  • 內(nèi)聯(lián)變量

  • 折疊表達式

  • constexpr lambda表達式

  • namespace嵌套

  • __has_include預處理表達式

  • 在lambda表達式用*this捕獲對象副本

  • 新增Attribute

  • 字符串轉(zhuǎn)換

  • std::variant

  • std::optional

  • std::any

  • std::apply

  • std::make_from_tuple

  • as_const

  • std::string_view

  • file_system

  • std::shared_mutex

下面,程序喵一一介紹:

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

在C++17前構(gòu)造一個模板類對象需要指明類型:

pair<int, double> p(1, 2.2); // before c++17

C++17就不需要特殊指定,直接可以推導出類型,代碼如下:

pair p(1, 2.2); // c++17 自動推導vector v = {1, 2, 3}; // c++17

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

通過結(jié)構(gòu)化綁定,對于tuple、map等類型,獲取相應值會方便很多,看代碼:

std::tuple<int, double> func() { return std::tuple(1, 2.2);}
int main() { auto[i, d] = func(); //是C++11的tie嗎?更高級 cout << i << endl; cout << d << endl;}
//==========================void f() { map<int, string> m = { {0, "a"}, {1, "b"}, }; for (const auto &[i, s] : m) { cout << i << " " << s << endl; }}
// ====================int main() { std::pair a(1, 2.3f); auto[i, f] = a; cout << i << endl; // 1 cout << f << endl; // 2.3f return 0;}

結(jié)構(gòu)化綁定還可以改變對象的值,使用引用即可:

// 進化,可以通過結(jié)構(gòu)化綁定改變對象的值int main() { std::pair a(1, 2.3f); auto& [i, f] = a; i = 2; cout << a.first << endl; // 2}

注意結(jié)構(gòu)化綁定不能應用于constexpr

constexpr auto[x, y] = std::pair(1, 2.3f); // compile error, C++20可以

結(jié)構(gòu)化綁定不止可以綁定pair和tuple,還可以綁定數(shù)組和結(jié)構(gòu)體等。

int array[3] = {1, 2, 3};auto [a, b, c] = array;cout << a << " " << b << " " << c << endl;
// 注意這里的struct的成員一定要是public的struct Point { int x; int y;};Point func() { return {1, 2};}const auto [x, y] = func();

這里其實可以實現(xiàn)自定義類的結(jié)構(gòu)化綁定,代碼如下:

// 需要實現(xiàn)相關(guān)的tuple_size和tuple_element和get<N>方法。class Entry {public: void Init() { name_ = "name"; age_ = 10; }
std::string GetName() const { return name_; } int GetAge() const { return age_; }private: std::string name_; int age_;};
template <size_t I>auto get(const Entry& e) { if constexpr (I == 0) return e.GetName(); else if constexpr (I == 1) return e.GetAge();}
namespace std { template<> struct tuple_size<Entry> : integral_constant<size_t, 2> {}; template<> struct tuple_element<0, Entry> { using type = std::string; }; template<> struct tuple_element<1, Entry> { using type = int; };}
int main() { Entry e; e.Init(); auto [name, age] = e; cout << name << " " << age << endl; // name 10 return 0;}

if-switch語句初始化

C++17前if語句需要這樣寫代碼:

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

C++17之后可以這樣:

// if (init; condition)
if (int a = GetValue()); a < 101) { cout << a;}
string str = "Hi World";if (auto [pos, size] = pair(str.find("Hi"), str.size()); pos != string::npos) { std::cout << pos << " Hello, size is " << size;}

使用這種方式可以盡可能約束作用域,讓代碼更簡潔,但是可讀性略有下降。

內(nèi)聯(lián)變量

C++17前只有內(nèi)聯(lián)函數(shù),現(xiàn)在有了內(nèi)聯(lián)變量,我們印象中C++類的靜態(tài)成員變量在頭文件中是不能初始化的,但是有了內(nèi)聯(lián)變量,就可以達到此目的:

// header filestruct A { static const int value; };inline int const A::value = 10;
// ==========或者========struct A { inline static const int value = 10;}

折疊表達式

C++17引入了折疊表達式使可變參數(shù)模板編程更方便:

template <typename ... Ts>auto sum(Ts ... ts) { return (ts + ...);}int a {sum(1, 2, 3, 4, 5)}; // 15std::string a{"hello "};std::string b{"world"};cout << sum(a, b) << endl; // hello world

constexpr lambda表達式

C++17前l(fā)ambda表達式只能在運行時使用,C++17引入了constexpr lambda表達式,可以用于在編譯期進行計算。

int main() { // c++17可編譯 constexpr auto lamb = [] (int n) { return n * n; }; static_assert(lamb(3) == 9, "a");}

注意

constexpr函數(shù)有如下限制:

函數(shù)體不能包含匯編語句、goto語句、label、try塊、靜態(tài)變量、線程局部存儲、沒有初始化的普通變量,不能動態(tài)分配內(nèi)存,不能有new delete等,不能虛函數(shù)。

namespace嵌套

namespace A { namespace B { namespace C { void func(); } }}
// c++17,更方便更舒適namespace A::B::C { void func();)}

__has_include預處理表達式

可以判斷是否有某個頭文件,代碼可能會在不同編譯器下工作,不同編譯器的可用頭文件有可能不同,所以可以使用此來判斷:

#if defined __has_include#if __has_include(<charconv>)#define has_charconv 1#include <charconv>#endif#endif
std::optional<int> ConvertToInt(const std::string& str) { int value{};#ifdef has_charconv const auto last = str.data() + str.size(); const auto res = std::from_chars(str.data(), last, value); if (res.ec == std::errc{} && res.ptr == last) return value;#else // alternative implementation... 其它方式實現(xiàn)#endif return std::nullopt;}

在lambda表達式用*this捕獲對象副本

正常情況下,lambda表達式中訪問類的對象成員變量需要捕獲this,但是這里捕獲的是this指針,指向的是對象的引用,正常情況下可能沒問題,但是如果多線程情況下,函數(shù)的作用域超過了對象的作用域,對象已經(jīng)被析構(gòu)了,還訪問了成員變量,就會有問題。

struct A { int a; void func() { auto f = [this] { cout << a << endl; }; f(); } };int main() { A a; a.func(); return 0;}

所以C++17增加了新特性,捕獲*this,不持有this指針,而是持有對象的拷貝,這樣生命周期就與對象的生命周期不相關(guān)啦。

struct A { int a; void func() { auto f = [*this] { // 這里 cout << a << endl; }; f(); } };int main() { A a; a.func(); return 0;}

新增Attribute

我們可能平時在項目中見過__declspec__, __attribute__ , #pragma指示符,使用它們來給編譯器提供一些額外的信息,來產(chǎn)生一些優(yōu)化或特定的代碼,也可以給其它開發(fā)者一些提示信息。

例如:

struct A { short f[3]; } __attribute__((aligned(8)));
void fatal() __attribute__((noreturn));

在C++11和C++14中有更方便的方法:

[[carries_dependency]] 讓編譯期跳過不必要的內(nèi)存柵欄指令[[noreturn]] 函數(shù)不會返回[[deprecated]] 函數(shù)將棄用的警告
[[noreturn]] void terminate() noexcept;[[deprecated("use new func instead")]] void func() {}

C++17又新增了三個:

[[fallthrough]]用在switch中提示可以直接落下去,不需要break,讓編譯期忽略警告

switch (i) {} case 1: xxx; // warning case 2: xxx; [[fallthrough]]; // 警告消除 case 3: xxx; break;}

使得編譯器和其它開發(fā)者都可以理解開發(fā)者的意圖。

[[nodiscard]] 表示修飾的內(nèi)容不能被忽略,可用于修飾函數(shù),標明返回值一定要被處理

[[nodiscard]] int func();void F() { func(); // warning 沒有處理函數(shù)返回值}

[[maybe_unused]] 提示編譯器修飾的內(nèi)容可能暫時沒有使用,避免產(chǎn)生警告

void func1() {}[[maybe_unused]] void func2() {} // 警告消除void func3() { int x = 1; [[maybe_unused]] int y = 2; // 警告消除}

字符串轉(zhuǎn)換

新增from_chars函數(shù)和to_chars函數(shù),直接看代碼:

#include <charconv>
int main() { const std::string str{"123456098"}; int value = 0; const auto res = std::from_chars(str.data(), str.data() + 4, value); if (res.ec == std::errc()) { cout << value << ", distance " << res.ptr - str.data() << endl; } else if (res.ec == std::errc::invalid_argument) { cout << "invalid" << endl; } str = std::string("12.34); double val = 0; const auto format = std::chars_format::general; res = std::from_chars(str.data(), str.data() + str.size(), value, format);
str = std::string("xxxxxxxx"); const int v = 1234; res = std::to_chars(str.data(), str.data() + str.size(), v); cout << str << ", filled " << res.ptr - str.data() << " characters \n"; // 1234xxxx, filled 4 characters}

std::variant

C++17增加std::variant實現(xiàn)類似union的功能,但卻比union更高級,舉個例子union里面不能有string這種類型,但std::variant卻可以,還可以支持更多復雜類型,如map等,看代碼:

int main() { // c++17可編譯 std::variant<int, std::string> var("hello"); cout << var.index() << endl; var = 123; cout << var.index() << endl;
try { var = "world"; std::string str = std::get<std::string>(var); // 通過類型獲取值 var = 3; int i = std::get<0>(var); // 通過index獲取對應值 cout << str << endl; cout << i << endl; } catch(...) { // xxx; } return 0;}

注意

一般情況下variant的第一個類型一般要有對應的構(gòu)造函數(shù),否則編譯失?。?br>

struct A { A(int i){}};int main() { std::variant<A, int> var; // 編譯失敗}

如何避免這種情況呢,可以使用std::monostate來打個樁,模擬一個空狀態(tài)。

std::variant<std::monostate, A> var; // 可以編譯成功

std::optional

我們有時候可能會有需求,讓函數(shù)返回一個對象,如下:

struct A {};A func() { if (flag) return A(); else { // 異常情況下,怎么返回異常值呢,想返回個空呢 }}

有一種辦法是返回對象指針,異常情況下就可以返回nullptr啦,但是這就涉及到了內(nèi)存管理,也許你會使用智能指針,但這里其實有更方便的辦法就是std::optional。

std::optional<int> StoI(const std::string &s) { try { return std::stoi(s); } catch(...) { return std::nullopt; }}
void func() { std::string s{"123"}; std::optional<int> o = StoI(s); if (o) { cout << *o << endl; } else { cout << "error" << endl; }}

std::any

C++17引入了any可以存儲任何類型的單個值,見代碼:

int main() { // c++17可編譯 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(); } a.reset(); if (a.has_value()) { cout << a.type().name(); } a = std::string("a"); cout << a.type().name() << " " << std::any_cast<std::string>(a) << endl; return 0;}

std::apply

使用std::apply可以將tuple展開作為函數(shù)的參數(shù)傳入,見代碼:

int add(int first, int second) { return first + second; }
auto add_lambda = [](auto first, auto second) { return first + second; };
int main() { std::cout << std::apply(add, std::pair(1, 2)) << '\n'; std::cout << add(std::pair(1, 2)) << "\n"; // error std::cout << std::apply(add_lambda, std::tuple(2.0f, 3.0f)) << '\n';}

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

通常我們傳遞一個string時會觸發(fā)對象的拷貝操作,大字符串的拷貝賦值操作會觸發(fā)堆內(nèi)存分配,很影響運行效率,有了string_view就可以避免拷貝操作,平時傳遞過程中傳遞string_view即可。

void func(std::string_view stv) { cout << stv << endl; }
int main(void) { std::string str = "Hello World"; std::cout << str << std::endl;
std::string_view stv(str.c_str(), str.size()); cout << stv << endl; func(stv); return 0;}

as_const

C++17使用as_const可以將左值轉(zhuǎn)成const類型

std::string str = "str";const std::string& constStr = std::as_const(str);

file_system

C++17正式將file_system納入標準中,提供了關(guān)于文件的大多數(shù)功能,基本上應有盡有,這里簡單舉幾個例子:

namespace fs = std::filesystem;fs::create_directory(dir_path);fs::copy_file(src, dst, fs::copy_options::skip_existing);fs::exists(filename);fs::current_path(err_code);

std::shared_mutex

C++17引入了shared_mutex,可以實現(xiàn)讀寫鎖,具體可以見我上一篇文章:C++14新特性的所有知識點全在這兒啦!

關(guān)于C++17的介紹就到這里,希望對大家有所幫助~

參考資料

https://en.cppreference.com/w/cpp/utility/make_from_tuple
https://en.cppreference.com/w/cpp/utility/apply
https://en.cppreference.com/w/cpp/17
https://cloud.tencent.com/developer/article/1383177
https://www.jianshu.com/p/9b8eeddbf1e4


C++14新特性的所有知識點全在這兒啦!

面試系列之C++的對象布局【建議收藏】


c++11新特性,所有知識點都在這了!

你的c++團隊還在禁用異常處理嗎?

JNI編程如何巧妙獲取JNIEnv

Linux 為什么要動態(tài)鏈接?與靜態(tài)鏈接的區(qū)別是什么?

內(nèi)存對齊之格式修訂版

c++11新特性之智能指針



免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉