一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

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

3天內(nèi)不再提示

C++變化很大!得重學(xué)這門語言了

CPP開發(fā)者 ? 來源:InfoQ ? 2023-07-09 16:09 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

Key Takeaways:

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

  • 有許多資源可以幫助我們學(xué)習(xí)現(xiàn)代 C++,包括 Godbolt 的編譯器探索器、ISOCpp 和 CppReference。

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

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

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

C++ 為何如重要

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

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

不管你的目標是哪種平臺,均需要一個編譯器。你還需要一個編輯器或集成開發(fā)環(huán)境(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 網(wǎng)站上有一個 FAQ 區(qū)域,概述了最近的一些變化,包括 C++11 和 C++14,以及整體的概覽。另外,還有多本關(guān)于 C++ 最近版本的圖書。

使用 Vector 快速了解 C++11

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

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

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

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

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

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

#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。這段代碼可以在編譯器探索器上找到。

類模板參數(shù)推斷

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

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

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

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

   std::vector numbers(18, 1);

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

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

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

Range

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

    #include 

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

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

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

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

  std::iota(sums, 1);

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

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

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

我們已經(jīng)得到了想要的數(shù)字三角,即 1,3,6,10,15……171。

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

std::vector<char> odd_or_even.

我們可以編寫一個簡短的函數(shù),它會獲取一個 int 并返回對應(yīng)的字符:

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

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

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

輸出將會如下所示:

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

看上去,我們確實是不斷地得到兩個奇數(shù),然后是兩個偶數(shù)。Stack Exchange 的數(shù)學(xué)網(wǎng)站闡述了出現(xiàn)這種現(xiàn)象的原因。

Lambdas

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

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

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

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

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

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

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

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

那么,我們就可以像調(diào)用有名稱的函數(shù)那樣調(diào)用它:

lambda(7);

這個特性允許我們使用 lambda 重寫轉(zhuǎn)換調(diào)用:

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

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

總 結(jié)

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

#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 循環(huán),瀏覽了移動語義,并練習(xí)了對 vector 的使用。對于首次重回 C++ 的人來說,這是一個不錯的起點!

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

關(guān)于作者

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


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • C++
    C++
    +關(guān)注

    關(guān)注

    22

    文章

    2119

    瀏覽量

    75328
  • 編輯器
    +關(guān)注

    關(guān)注

    1

    文章

    822

    瀏覽量

    32045
  • Vector
    +關(guān)注

    關(guān)注

    3

    文章

    76

    瀏覽量

    9262

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

文章出處:【微信號:CPP開發(fā)者,微信公眾號:CPP開發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    C語言C++的區(qū)別

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

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

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

    C語言C++運用

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

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

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

    c++程序設(shè)計語言題解

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

    CodeWarrior C and C++ and Assembly 語言參考設(shè)計

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

    CC++語言參考手冊

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

    C/C++編程語言學(xué)習(xí)難點及語言

    一般學(xué)C++前都要學(xué)C,所以通常叫它們C/C++。C/C++歷經(jīng)40余年,也是經(jīng)久不衰的號稱“永
    發(fā)表于 08-15 10:24 ?2445次閱讀

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

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

    C語言C++相互調(diào)用

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

    C語言C++到底是什么關(guān)系

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

    C++語言的發(fā)展

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

    如何選擇創(chuàng)建c語言c++

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

    vb語言c++語言的區(qū)別

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

    c語言,c++,java,python區(qū)別

    C語言C++、Java和Python是四種常見的編程語言,各有優(yōu)點和特點。 C語言
    的頭像 發(fā)表于 02-05 14:11 ?3252次閱讀