日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
他來了,他來了,C++17新特性精華都在這了

本文轉(zhuǎn)載自微信公眾號「程序喵大人」,作者程序喵大人 。轉(zhuǎn)載本文請聯(lián)系程序喵大人公眾號。

王屋網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項目制作,到程序開發(fā),運營維護。創(chuàng)新互聯(lián)自2013年創(chuàng)立以來到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。

程序喵之前已經(jīng)介紹過C++11的新特性和C++14的新特性(點擊對應(yīng)文字,直接訪問),今天向親愛的讀者們介紹下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)造一個模板類對象需要指明類型:

 
 
 
  1. pair p(1, 2.2); // before c++17

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

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

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

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

 
 
 
  1. std::tuple func() {
  2.    return std::tuple(1, 2.2);
  3. }
  4. int main() {
  5.    auto[i, d] = func(); //是C++11的tie嗎?更高級
  6.    cout << i << endl;
  7.    cout << d << endl;
  8. }
  9. //==========================
  10. void f() {
  11.    map m = {
  12.     {0, "a"},
  13.     {1, "b"},  
  14.   };
  15.    for (const auto &[i, s] : m) {
  16.        cout << i << " " << s << endl;
  17.   }
  18. }
  19. // ====================
  20. int main() {
  21.    std::pair a(1, 2.3f);
  22.    auto[i, f] = a;
  23.    cout << i << endl; // 1
  24.    cout << f << endl; // 2.3f
  25.    return 0;
  26. }

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

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

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

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

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

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

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

 
 
 
  1. // 需要實現(xiàn)相關(guān)的tuple_size和tuple_element和get方法。
  2. class Entry {
  3. public:
  4.    void Init() {
  5.        name_ = "name";
  6.        age_ = 10;
  7.   }
  8.    std::string GetName() const { return name_; }
  9.    int GetAge() const { return age_; }
  10. private:
  11.    std::string name_;
  12.    int age_;
  13. };
  14. template 
  15. auto get(const Entry& e) {
  16.    if constexpr (I == 0) return e.GetName();
  17.    else if constexpr (I == 1) return e.GetAge();
  18. }
  19. namespace std {
  20.    template<> struct tuple_size : integral_constant {};
  21.    template<> struct tuple_element<0, Entry> { using type = std::string; };
  22.    template<> struct tuple_element<1, Entry> { using type = int; };
  23. }
  24. int main() {
  25.    Entry e;
  26.    e.Init();
  27.    auto [name, age] = e;
  28.    cout << name << " " << age << endl; // name 10
  29.    return 0;
  30. }

if-switch語句初始化

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

 
 
 
  1. int a = GetValue();
  2. if (a < 101) {
  3.    cout << a;
  4. }

C++17之后可以這樣:

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

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

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

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

 
 
 
  1. // header file
  2. struct A {
  3.    static const int value;  
  4. };
  5. inline int const A::value = 10;
  6. // ==========或者========
  7. struct A {
  8.    inline static const int value = 10;
  9. }

折疊表達式

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

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

constexpr lambda表達式

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

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

注意

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

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

namespace嵌套

 
 
 
  1. namespace A {
  2.    namespace B {
  3.        namespace C {
  4.            void func();
  5.       }
  6.   }
  7. }
  8. // c++17,更方便更舒適
  9. namespace A::B::C {
  10.    void func();)
  11. }

__has_include預處理表達式

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

 
 
 
  1. #if defined __has_include
  2. #if __has_include()
  3. #define has_charconv 1
  4. #include 
  5. #endif
  6. #endif
  7. std::optional ConvertToInt(const std::string& str) {
  8.    int value{};
  9. #ifdef has_charconv
  10.    const auto last = str.data() + str.size();
  11.    const auto res = std::from_chars(str.data(), last, value);
  12.    if (res.ec == std::errc{} && res.ptr == last) return value;
  13. #else
  14.    // alternative implementation...
  15.    其它方式實現(xiàn)
  16. #endif
  17.    return std::nullopt;
  18. }

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

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

 
 
 
  1. struct A {
  2.    int a;
  3.    void func() {
  4.        auto f = [this] {
  5.            cout << a << endl;
  6.       };
  7.        f();
  8.   }  
  9. };
  10. int main() {
  11.    A a;
  12.    a.func();
  13.    return 0;
  14. }

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

 
 
 
  1. struct A {
  2.    int a;
  3.    void func() {
  4.        auto f = [*this] { // 這里
  5.            cout << a << endl;
  6.       };
  7.        f();
  8.   }  
  9. };
  10. int main() {
  11.    A a;
  12.    a.func();
  13.    return 0;
  14. }

新增Attribute

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

例如:

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

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

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

C++17又新增了三個:

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

 
 
 
  1. switch (i) {}
  2.     case 1:
  3.         xxx; // warning
  4.     case 2:
  5.         xxx;
  6.         [[fallthrough]];      // 警告消除
  7.     case 3:
  8.         xxx;
  9.        break;
  10. }

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

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

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

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

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

字符串轉(zhuǎn)換

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

 
 
 
  1. #include 
  2. int main() {
  3.     const std::string str{"123456098"};
  4.     int value = 0;
  5.     const auto res = std::from_chars(str.data(), str.data() + 4, value);
  6.     if (res.ec == std::errc()) {
  7.         cout << value << ", distance " << res.ptr - str.data() << endl;
  8.     } else if (res.ec == std::errc::invalid_argument) {
  9.         cout << "invalid" << endl;
  10.     }
  11.     str = std::string("12.34);
  12.     double val = 0;
  13.     const auto format = std::chars_format::general;
  14.     res = std::from_chars(str.data(), str.data() + str.size(), value, format);
  15.     str = std::string("xxxxxxxx");
  16.     const int v = 1234;
  17.     res = std::to_chars(str.data(), str.data() + str.size(), v);
  18.     cout << str << ", filled " << res.ptr - str.data() << " characters \n";
  19.     // 1234xxxx, filled 4 characters
  20. }

注意

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

 
 
 
  1. struct A {
  2.     A(int i){}
  3. };
  4. int main() {
  5.     std::variant var; // 編譯失敗
  6. }

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

 
 
 
  1. std::variant var; // 可以編譯成功

std::optional

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

 
 
 
  1. struct A {};
  2. A func() {
  3.     if (flag) return A();
  4.     else {
  5.         // 異常情況下,怎么返回異常值呢,想返回個空呢
  6.     }
  7. }

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

 
 
 
  1. std::optional StoI(const std::string &s) {
  2.     try {
  3.         return std::stoi(s);
  4.     } catch(...) {
  5.         return std::nullopt;
  6.     }
  7. }
  8. void func() {
  9.     std::string s{"123"};
  10.     std::optional o = StoI(s);
  11.     if (o) {
  12.         cout << *o << endl;
  13.     } else {
  14.         cout << "error" << endl;
  15.     }
  16. }

std::any

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

 
 
 
  1. int main() { // c++17可編譯
  2.     std::any a = 1;
  3.     cout << a.type().name() << " " << std::any_cast(a) << endl;
  4.     a = 2.2f;
  5.     cout << a.type().name() << " " << std::any_cast(a) << endl;
  6.     if (a.has_value()) {
  7.         cout << a.type().name();
  8.     }
  9.     a.reset();
  10.     if (a.has_value()) {
  11.         cout << a.type().name();
  12.     }
  13.     a = std::string("a");
  14.     cout << a.type().name() << " " << std::any_cast(a) << endl;
  15.     return 0;
  16. }

std::apply

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

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

std::make_from_tuple

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

 
 
 
  1. struct Foo {
  2.     Foo(int first, float second, int third) {
  3.         std::cout << first << ", " << second << ", " << third << "\n";
  4.     }
  5. };
  6. int main() {
  7.    auto tuple = std::make_tuple(42, 3.14f, 0);
  8.    std::make_from_tuple(std::move(tuple));
  9. }

std::string_view

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

 
 
 
  1. void func(std::string_view stv) { cout << stv << endl; }
  2. int main(void) {
  3.     std::string str = "Hello World";
  4.     std::cout << str << std::endl;
  5.     std::string_view stv(str.c_str(), str.size());
  6.     cout << stv << endl;
  7.     func(stv);
  8.     return 0;
  9. }

as_const

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

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

file_system

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

 
 
 
  1. namespace fs = std::filesystem;
  2. fs::create_directory(dir_path);
  3. fs::copy_file(src, dst, fs::copy_options::skip_existing);
  4. fs::exists(filename);
  5. 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++17新特性精華都在這了
網(wǎng)站鏈接:http://m.5511xx.com/article/coscoei.html