在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

C++變化很大!得重學這門語言了

CPP開發者 ? 來源:InfoQ ? 2023-07-09 16:09 ? 次閱讀

Key Takeaways:

  • C++ 依然非常重要,而且將會永遠如此。

  • 有許多資源可以幫助我們學習現代 C++,包括 Godbolt 的編譯器探索器、ISOCpp 和 CppReference。

  • C++ 可以比以前更加簡單。除了便利性相關的增強外,潛在的性能改善也是 C++11 和后續標準的驅動力之一。

  • 我們通過填充一個 vector 并輸出其內容進行練習。我們通過在 vector 上使用算法、range 和 lambda,以便于尋找具有特定屬性的元素,實現進一步的練習。

C++ 是一門古老但不斷演進的語言。你幾乎可以使用它來做任何事情,而且可以在很多地方找到它的身影。實際上,C++ 的發明者 Bjarne Stroustrup 將其描述為一切事物的隱形基礎。有時,它可以深入到另外一門語言的庫中,因為 C++ 可以用于性能關鍵的路徑中。它可以在小型的嵌入式系統中運行,也可以為視頻游戲提供動力。你的瀏覽器可能正在使用它。C++ 幾乎無處不在!

C++ 為何如重要

迄今為止,C++ 已經存在了很長的時間,但是其變化也是非常大的,尤其是 2011 年之后。當時,推出了一個名為 C++11 的新標準,標志著一個頻繁更新的時代正式開啟。如果你從 C++11 就沒有使用過 C++,那么你有很多東西需要補習,這要從哪里開始呢?

該語言是需要編譯的,面向特定的架構,如 PC、大型機、嵌入式設備、定制硬件,或者你想到的其他東西。如果你需要代碼在不同類型的機器上運行,那需要重新編譯它。這有缺點也有優點。不同的配置會帶來更多的維護工作,但編譯到特定架構能夠讓你“因地制宜(down to the metal)”,從而獲得速度方面的優勢。

不管你的目標是哪種平臺,均需要一個編譯器。你還需要一個編輯器或集成開發環境(IDE)來編寫 C++ 代碼。ISOCpp 給出了一個資源清單,包括 C++ 編譯器。Gnu 編譯器集(Gnu compiler collection,gcc)、Clang 和 Visual Studio 均有免費版本。你甚至可以使用 Matt Godbolt 的編譯器探索器,在瀏覽器上嘗試基于各種編譯器的代碼。編譯器可能支持不同版本的 C++,所以必須在編譯器標記中說明你所需要的版本,例如 g++ 的 -std=c++23 或 Visual Studio 的 /std:c++latest。ISOCpp 網站上有一個 FAQ 區域,概述了最近的一些變化,包括 C++11 和 C++14,以及整體的概覽。另外,還有多本關于 C++ 最近版本的圖書。

使用 Vector 快速了解 C++11

如果你已經被落下了,那么大量的資源可能會讓你不知所措。但是,我們可以通過一個小例子來理解一些基礎知識。停下來,親自動手試一試往往是最好的學習方法。因此,我們從簡單基礎的東西開始吧!

一個很有用(且簡單)的起點是不太起眼的 vector,它位于 std 命名空間的 vector 頭文件中。CppReference 提供了一個概述,告訴我們 vector 是一個序列容器,封裝了動態大小的數組。因此,vector 包含了一個連續的元素序列,我們可以根據需要調整 vector 的大小。vector 本身是一個類模板,因此它需要一個類型,例如 std::vector。我們可以使用 push_back 將一個條目添加到 vector 的尾部。C++11 引入了一個名為 emplace_back 的新方法,該方法取值來構造一個新的條目。對于 int,代碼看上去是一樣的:

std::vector<int> numbers;
numbers.push_back(1);
numbers.emplace_back(1);

如果我們有比 int 更復雜的東西,那么就可能在 emplace 版本中獲得性能方面的收益,因為 emplace 版本可以就地構造條目,從而避免對其進行復制。

C++11 引入了 r-value 引用和移動語義(move semantics)來避免不必要的復制。潛在的性能改善是 C++11 的驅動力之一,后續的版本都是在此基礎上進行的。為了解釋什么是 r-value 引用,我們可以考慮前面樣例中的 push_back 方法。它有兩個重載形式,其中一個會接受一個常量引用,即 const T& 值,另外一個接受一個 r-value 引用,即 T&& 值。第二個版本會將元素移動到 vector 中,這可以避免復制臨時對象。與之類似,emplace_back 的簽名通過 r-value 引用來獲取參數,Args&&…,同樣允許移動參數而無需復制。移動語義是一個很大的話題,我們只是接觸到了它的皮毛。如果你想了解更多詳情的話,Thomas Becker 在 2013 年撰寫了一篇很好的文章,介紹了它的細節。

我們創建一個 vector 并在其中放置幾個條目,然后使用來自 iostream 頭文件的 std::cout 展示其內容。我們使用流插入操作符<<來顯示這些元素。我們基于 vector 的 size 編寫一個 for 循環,并使用操作符 [] 來訪問每個元素:

#include 
#include 
void warm_up()
{
    std::vector<int> numbers;
    numbers.push_back(1);
    numbers.emplace_back(1);
    for(int i=0; i
    {
        std::cout << numbers[i] << ' ';
    }
    std::cout << '
';
}
int main()
{
    warm_up();
}

該代碼會顯示兩個 1。這段代碼可以在編譯器探索器上找到。

類模板參數推斷

讓我們做一些更有意思的事情,并學習一下現代的 C++。我們構建幾個數字三角,會發現它們之間存在一個模式。數字三角的值是 1,3,6,10……它們分別由 1,1+2,1+2+3,1+2+3+4,……相加而成。如果我們這些斯諾克球架起來,就可以組成一個三角形,它也因此得名:

7fc13678-1e0c-11ee-962d-dac502259ad0.png

如果再增加一排,我們就會再增加六個斯諾克球。再加一排就會增加七個,以此類推。

為了得到數字 1,2,3 等,我們可以構建一個充滿 1 的 vector,然后將這些數字相加。我們可以直接創建一個 vector,比如 18 個 1,而不必再增加另一個循環。我們說明想要多少個元素,然后再指明它的值:

   std::vector numbers(18, 1);

注意我們不需要再聲明了。因為從 C++17 開始,類模板參數推斷(CTAD)就已經實現了。編譯器可以推斷出我們指的是 int,因為我們要求的值是 1,這是一個 int。如果我們需要顯示 vector,那么可以使用基于 range 的 for 循環。此時,我們不必使用基于 vector 索引的傳統 for 循環,而是聲明一個類型,甚至可以使用新的關鍵字 auto,告訴編譯器判斷類型,然后是冒號和容器:

   for (auto i : numbers)
    {
        std::cout << i << ' ';
    }
    std::cout << '
';

CTAD 和基于 range 的 for 循環是 C++11以來引入的一些便利特性。

Range

有了由“1”組成的 vector,我們就可以包含numeric頭文件,并使用部分的和來填充一個新的vector,如 1,1+1,1+1+1……,這樣就有了 1,2,3……我們需要聲明新vector的類型,因為這里要從一個空的vector開始,如果沒有任何值可供使用,那么編譯器將無法推斷其類型。partial_sum需要開頭和結尾的數字,最后我們需要使用back_inserter,這樣目標 vector 會根據需要增長:

    #include 

    std::vector numbers(18, 1);
    std::vector<int> sums;
    std::partial_sum(numbers.begin(), numbers.end(),
        std::back_inserter(sums));

這樣我們就得到了 1 到 18 的數字,均包含邊界值。我們已經完成了數字三角的部分工作,但是 C++ 現在可以讓我們的代碼更加簡潔。C++11 引入了?iota?函數,也位于numeric頭文件中,它能夠用不斷增加的值填充一個容器:

std::vector<int> sums(18);
std::iota(sums.begin(), sums.end(), 1);

實際上,C++23引入了一個range版本,它會為我們找到對應的begin和end:

  std::iota(sums, 1);

C++23 還沒有得到廣泛的支持,所以可能需要等到你的編譯器提供 range 版本。numeric 和 algorithm 頭文件中的很多算法都有兩個版本,其中一個需要一對輸入迭代器(即 first and last),另一個則是 range 版本,只需要接受容器即可。ranges 重載正在逐漸添加到標準 C++ 中。ranges 提供的功能遠遠超過我們這里避免聲明兩個迭代器的場景。我們可以過濾和轉換輸出,將這些東西連接在一起,并使用視圖來避免復制數據。ranges 支持惰性計算,所以視圖的內容會在需要的時候才評估計算出來。Ivan ?uki?的 Functional Programming in C++ 一書在這方面提供了更多的細節(書中還包含更多的內容)。

我們需要做的最后一件事就是形成數字三角。查看 vector 的部分和:

   std::partial_sum(sums.begin(), sums.end(), sums.begin());

我們已經得到了想要的數字三角,即 1,3,6,10,15……171。

我們注意到,有些算法有 ranges 版本,那我們可以嘗試一個。前兩個三角數字是 1 和 3 是奇數,然后是兩個偶數 6 和 10。這個模式是不是可持續的呢?如果我們對 vector 進行轉換,用點號“.”來標記奇數,用星號“*”來標記偶數,就能看出最終結果。我們可以聲明一個新的 vector 來存放轉換結果。對于每個數字,僅需要一個字符,所以我們需要一個 char 類型的 vector:

std::vector<char> odd_or_even.

我們可以編寫一個簡短的函數,它會獲取一個 int 并返回對應的字符:

char flag_odd_or_even(int i)
{
    return i % 2 ? '.' : '*';
}

如果 i % 2 的值不為零,這就是一個奇數,所以我們返回.,否則,返回 *。我們可以在來自 algorithm 頭文件的 transform 函數中使用這個自己的函數。最初的版本需要一對輸入迭代器(first 和 last)、一個輸出迭代器和一個一元函數(unary function),該函數會接受一個輸入,就像我們的 flag_odd_or_even 函數這樣。C++20 引入了一個 ranges 版本,它能夠接受一個輸入源,而不是一對迭代器,另外還需要一個輸出迭代器和一元函數。這意味著我們可以通過如下方式來轉換先前生成的和:

   std::vector<char> odd_or_even;
    std::transform(sums,
        std::back_inserter(odd_or_even),
        flag_odd_or_even);

輸出將會如下所示:

. . * * . . * * . . * * . . * * . .

看上去,我們確實是不斷地得到兩個奇數,然后是兩個偶數。Stack Exchange 的數學網站闡述了出現這種現象的原因。

Lambdas

我們使用另一個新的 C++ 特性對我們的代碼做最后的改進。如果我們想要看一下實際的轉換代碼的話,那需要要轉移到另外一個地方才能看到這個一元函數都做了些什么。

C++11 引入了匿名函數或 lambda 表達式的特性。它們看起來與有名稱的函數類似,將參數放在括號中,將函數主體放到花括號中,但是它們沒有名字,不需要返回類型,并且有一個用 [] 表示的捕獲組:

[](int i) { return i%2? '.':'*'; }

如果與有名稱的函數進行對比,會看到兩者的相似性:

char flag_odd_or_even(int i){ return i % 2 ? '.' : '*'; }

我們可以在捕獲組中聲明變量,這會給我們一個閉包。這些內容超出了本文的范圍,但是在函數式編程中它們是非常強大和常見的。

如果我們將一個 lambda 分配給一個變量,

auto lambda = [](int i) { return i % 2 ? '.' : '*'; };

那么,我們就可以像調用有名稱的函數那樣調用它:

lambda(7);

這個特性允許我們使用 lambda 重寫轉換調用:

    std::transform(sums,
        std::back_inserter(odd_or_even),
        [](int i) { return i%2? '.':'*'; });

這樣的話,我們就可以在一個地方看到轉換函數,而不必再去查看其他的地方了。

總 結

將所有的內容組合在一起,就形成了如下的代碼:

#include 
#include 
#include 
#include 
int main()
{
    std::vector<int> sums(18);
    std::iota(sums.begin(), sums.end(), 1);
    std::partial_sum(sums.begin(), sums.end(), sums.begin());
    std::vector<char> odd_or_even;
    std::transform(sums,
        std::back_inserter(odd_or_even),
        [](int i) { return i%2? '.':'*'; });
    for (auto c : odd_or_even)
    {
        std::cout << c << ' ';
    }
    std::cout << '
';
}

我們使用了 ranges、lambda 和基于 range 的 for 循環,瀏覽了移動語義,并練習了對 vector 的使用。對于首次重回 C++ 的人來說,這是一個不錯的起點!

你可以在編譯器探索器中嘗試上述的代碼。

關于作者

Frances Buontempo,Frances Buontempo 有多年的 C++ 經驗,還有過使用 Python 和其他各種語言的經驗。她曾發表過關于 C++ 的演講,并且是 ACCU 的 Overload 雜志的編輯。她有數學背景,為 PragProg 寫了一本關于遺傳算法和機器學習的書,并且正在為 Manning 寫一本名為 C++ Bookcamp 的 C++ 書,以幫助那些被現代 C++ 落下的人迎頭趕上。


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C++
    C++
    +關注

    關注

    22

    文章

    2117

    瀏覽量

    74853
  • 編輯器
    +關注

    關注

    1

    文章

    818

    瀏覽量

    31845
  • Vector
    +關注

    關注

    3

    文章

    73

    瀏覽量

    9110

原文標題:C++ 變化很大!得重學這門語言了

文章出處:【微信號:CPP開發者,微信公眾號:CPP開發者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    C語言C++的區別

    很大程度上,C++C的超集,這意味著一個有效的C程序也是一個有效的C++程序。
    發表于 09-16 10:20 ?1291次閱讀

    C語言C++中那些不同的地方

    C語言雖說經常和C++在一起被大家提起,但可千萬不要以為它們是一個東西。現在我們常用的C語言C
    的頭像 發表于 12-07 14:29 ?1481次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>和<b class='flag-5'>C++</b>中那些不同的地方

    C語言C++運用

    很多同學在大學都學過CC++,那么CC++就業怎么樣?薪資高嗎?小編今天就給大家詳細解讀一下。學c++ 好不好?
    發表于 11-25 10:47

    c++程序設計語言(特別版)

    c++程序設計語言介紹標準C++以及由C++所支持的關鍵性編程技術和設計技術。標準C++較以前
    發表于 09-05 15:28 ?0次下載

    c++程序設計語言題解

    c++程序設計語言題解是與Bjarne Stroustrup的《C++程序設計語言》一書配套使用的習題解答,為從《C++程序設計
    發表于 09-05 16:00 ?121次下載
    <b class='flag-5'>c++</b>程序設計<b class='flag-5'>語言</b>題解

    CodeWarrior C and C++ and Assembly 語言參考設計

    本文是英文版的,介紹CodeWarrior C and C++ and Assembly 語言參考設計,在您的設計中或許有用:
    發表于 06-22 15:33 ?74次下載

    CC++語言參考手冊

    CC++語言參考手冊
    發表于 06-19 11:12 ?23次下載

    C/C++編程語言學習難點及語言

    一般學C++前都要學C,所以通常叫它們C/C++C/C++歷經40余年,也是經久不衰的號稱“永
    發表于 08-15 10:24 ?2400次閱讀

    40年后C++為何仍然當今使用最廣泛的編程語言之一?

    強大、靈活、復雜:C++ 的起源可以追溯到 40 年前,但它仍然是當今使用最廣泛的編程語言之一。為了找出原因,TechRepublic 采訪 C++ 之父 Bjarne Strous
    的頭像 發表于 02-15 11:18 ?3106次閱讀

    C語言C++相互調用

    接口的問題,比如最常用的C++調用C的接口來完成相應的外設驅動接口。 我們知道C++幾乎是完全兼容C的,不同的編譯語言都有其自身的一套編譯規
    的頭像 發表于 01-18 11:05 ?3576次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>與<b class='flag-5'>C++</b>相互調用

    C語言C++到底是什么關系

    首先C++C語言本來就是兩種不同的編程語言,但C++確實是對C
    的頭像 發表于 06-20 11:28 ?5702次閱讀

    C++語言的發展

    今年的CPP North C++大會上,谷歌宣布一門新的編程語言Carbon,并稱其將是“C++的繼任者”。
    發表于 08-15 14:22 ?753次閱讀

    如何選擇創建c語言c++

    選擇創建 C 語言C++ 都需要綜合考慮多個因素。在決定使用哪種語言之前,我們需要對這兩種語言的特點、優缺點、適用場景、學習成本等進行全
    的頭像 發表于 11-27 15:58 ?907次閱讀

    vb語言c++語言的區別

    VB語言C++語言是兩種不同的編程語言,雖然它們都屬于高級編程語言,但在設計和用途上有很多區別。下面將詳細比較VB
    的頭像 發表于 02-01 10:20 ?3188次閱讀

    c語言,c++,java,python區別

    C語言C++、Java和Python是四種常見的編程語言,各有優點和特點。 C語言
    的頭像 發表于 02-05 14:11 ?3110次閱讀
    主站蜘蛛池模板: 啪啪免费网站 | 骚五月| 天天舔天天操 | 天天天天做夜夜夜做 | 男女交性视频免费 | 99色99| 午夜黄色剧场 | 国产伦精品一区二区三区四区 | 99久热只有精品视频免费观看17 | 色综合成人丁香 | 美女被羞羞产奶视频网站 | 日本三级在线观看免费 | 性生大片免费观看无遮挡 | 黄网站视频观看免费 | 亚洲网站在线看 | a级精品九九九大片免费看 a级毛毛片看久久 | 免费抓胸吻胸激烈视频网站 | 天堂网中文在线 | 天天干人人 | 日本人视频-jlzz jlzz jlzz | 欧美区一区 | 国产精品久久久亚洲第一牛牛 | 伊人不卡久久大香线蕉综合影院 | 白丝丝袜高跟国产在线视频 | 免费国产成高清人在线视频 | 午夜宅男在线 | 草草影院www色极品欧美 | 久久综合九色综合欧洲色 | 特级淫片aaaaa片毛片 | 一区二区三区四区在线观看视频 | 香蕉网影院在线观看免费 | 极品吹潮视频大喷潮tv | 特污兔午夜影院 | 六月婷婷激情 | 午夜影院美女 | 日本黄色片免费看 | 色婷婷综合在线视频最新 | 中国女人a毛片免费全部播放 | 国产精品超清大白屁股 | 亚洲综合色网 | 四虎成人欧美精品在永久在线 |