C++ Primer 標準庫vector

歡迎閱讀我的 【C++Primer】專欄

專欄簡介:本專欄主要面向C++初學者,解釋C++的一些基本概念和基礎語言特性,涉及C++標準庫的用法,面向對象特性,泛型特性高級用法。通過使用標準庫中定義的抽象設施,使你更加適應高級程序設計技術。希望對讀者有幫助!

在這里插入圖片描述
在這里插入圖片描述

目錄

  • 3.3標準庫Vector
    • 定義和初始化vector對象通
    • 列表初始化vector對象
    • 創建指定數量的元素
    • 值初始化
    • 列表初始值還是元素數量?
    • 向vector對象中添加元素
    • 向vector對象添加元素蘊含的編程假定
    • 其他vector操作
    • 計算vector內對象的索引
    • 不能用下標形式添加元素

3.3標準庫Vector

標準庫類型vector表示對象的集合,其中所有對象的類型都相同。集合中的每個對象都有一個與之對應的索引,索引用于訪問對象。因為vector“容納著“其他對象,所以它也常被稱作容器(container)。

要想使用vector,必須包含適當的頭文件。在后續的例子中,都將假定做了如下using聲明;

#include<vector>
usingstd::vector;

C++語言既有類模板(classtemplate),也有函數模板,其中vector是一個類模板。只有對C++有了相當深入的理解才能寫出模板,事實上,我們直到第16章才會學習如何自定義模板。幸運的是,即使還不會創建模板,我們也可以先試著用用它。

模板本身不是類或函數,相反可以將模板看作為編譯器生成類或函數編寫的一份說明。編譯器根據模板創建類或函數的過程稱為實例化(instantiation),當使用模板時,需要指出編譯器應把類或函數實例化成何種類型。

對于類模板來說,我們通過提供一些額外信息來指定模板到底實例化成什么樣的類,需要提供哪些信息由模板決定。提供信息的方式總是這樣:即在模板名字后面跟一對尖括號,在括號內放上信息。
以vector為例,提供的額外信息是vector內所存放對象的類型:

    vector<int> ivec;//ivec保存int類型的對象vector<Sales_item> Sales_vec//保孫Salesitem類型的對象vector<vector<string>> file;//該向量的元素是vectoz對象

在上面的例子中,編詳器根據模板vector生成了三種不同的類型,vector、vector<Sales_item>和 vector<vector>。vector是模板而非類型,由vector生成的類型必須包含vector中元素的類型,例如yector。

vector能容納絕大多數類型的對象作為其元素,但是因為引用不是對象,所以不存在包含引用的vector。除此之外,其他大多數(非引用內置類型和類類型都可以構成vector對象,甚至組成vector的元素也可以是vector。

需要指出的是,在早期版本的C++標準中如果vector的元素還是vector(或者其他模板類型),則其定義的形式與現在的C++11新標準略有不同。過去,必須在外層vector對象的右尖括號和其元素類型之間添加一個空格,如應該寫成vector<vector >而非vector<vector>

WARNNING :某些編譯器可能仍需以老式的聲明語句來處理元素為vector的vector對象,如vector<vector > 。

定義和初始化vector對象通

和任何一種類類型一樣,vector模板控制著定義和初始化向量的方法。表3.4列出了定義vector對象的常用方法。

表3.4:初始化vector對象的方法

vectorv1v1是一個空vector,它潛在的元素是類型的,執行默認初始化
vectorv2(v1)v2中包含有v1所有元素的副本
vectorv2 =v1等價于v2(v1),v2中包含有v1所有元素的副本
vectorv3(n,val)v3包含了n個重復的元素,每個元素的值都是val
vectorv4(n)v4包含了n個重復地執行了值初始化的對象
vectorv5{ta,b,c…)v5包含了初始值個數的元素,每個元素被賦予相應的初始值
vectorv5=ta,b,c…)等價于v5tarbyc…

可以默認初始化vector對象,從而創建一個指定類型的空 vector:

vector<string>syec; //默認初始化,svec不含任何元素

看起來空vector好像沒什么用,但是很快我們就會知道程序在運行時可以很高效地往vector對象中添加元素。事實上,最常見的方式就是先定義一個空vector,然后當運行時獲取到元素的值后再逐一添加。

當然也可以在定義vector對象時指定元素的初始值。例如,允許把一個vector對象的元素拷貝給另外一個vector對象。此時,新vector對象的元素就是原vector對象對應元素的副本。注意兩個vector對象的類型必須相同:

vector<int> ivec;//初始狀態為空
//在此處給ivec添加一些值
vector<int> ivec2(ivec);//把tvec的元素拷貝給ivec2
vector<int> tvec3=ivecy;//把ivec的元素拷貝給ivec3
vector<string> svec(tvec2);//錯誤:svec的元素是string對象,不是tnt

列表初始化vector對象

C++11新標準還提供了另外一種為vector對象的元素賦初值的方法,即列表初始化。此時,用花括號擔起來的0個或多個初始元素值被賦給vector對象:

vector<string> articles = {“a“,“an“,“the“};

上述vector對象包含三個元素:第一個是字符串“a“,第二個是字符串“an“,最后一個是字符串“the“。

之前已經講過,C++語言提供了幾種不同的初始化方式。在大多數情況下這些初始化方式可以相互等價地使用,不過也并非一直如此。目前已經介紹過的兩種例外情況是:其一,使用拷貝初始化時(即使用=時),只能提供一個初始值;其二,如果提供的是一個類內初始值,則只能使用拷貝初始化或使用花括號的形式初始化。第三種特殊的要求是,如果提供的是初始元素值的列表,則只能把初始值都放在花括號里進行列表初始化,而不能放在圓括號里:

vector<string>V1{“a“,“anm,“the“};//列表初始化
vector<string>v2(“a“,“an“,“the“);//錯誤

創建指定數量的元素

還可以用vector對象容納的元素數量和所有元素的統一初始值來初始化vector對象:

vector<int>ivec(10,-1)}//10個int類型的元素,每個都被初始化為-1
vector<string>svec(10,“hi!);//10個string類型的元素,//每個都被初始化為“hi1

值初始化

通常情況下,可以只提供vector對象容納的元素數量而不用略去初始值。此時庫會創建一個值初始化的(value-initialized)元素初值,并把它賦給容器中的所有元素。這個初值由vector對象中元素的類型決定。

如果vector對象的元素是內置類型,比如int,則元素初始值自動設為0。如果元素是桅種類類型,比如string,則元素由類默認初始化:

vector<int>ivec(10);     //10個元素,每個都初始化為0
vector<string>svec(10);  //10個元素,參個都是空string對象

對這種初始化的方式有兩個特殊限制:其一,有些類要求必須明確地提供初始值,如果vector對象中元素的類型不支持默認初始化,我們就必須提供初始的元素值.對這種類型的對象來說,只提供元素的數量而不設定初始值無法完成初始化工作。

其二,如果只提供了元素的數量而沒有設定初始值,只能使用直接初始化:

vector<int>vi=10;//錯誤:必須使用直接初始化的形式指定向量大小

這里的10是用來說明如何初始化vector對象的,我們用它的本意是想創建含有10個值初始化了的元素的vector對象,而非把數字10“拷貝“到vector中。因此,此時不定使用拷貝初始化。

列表初始值還是元素數量?

在某些情況下,初始化的真實含義依賴于傳遞初始值時用的是花括號還是圓括號。例如,用一個整數來初始化vector時,整數的含義可能是vector對象的容量也可能是元素的值。類似的,用兩個整數來初始化vector時,這兩個整數可能一個是vector對象的容量,另一個是元素的初值,也可能它們是容量為2的vector對象中兩個元素的初值。通過使用花括號或圓括號可以區分上述這些含義:

vector<int>v1(10);//vl有10個元素,每個的值都是0
vector<int>v2{10};//v2有1個元素,該元素的值是10
vector<int>v3(10,1);//v3有10個元素,每個的值都是1
vector<int>v4{10,1};//v4有2個元素,值分別是10和1

如果用的是圓括號,可以說提供的值是用秈構造Cconstruct)vectoz對象的。例如,v1的初始值說明了vector對象的容量;v3的兩個初始值則分別說明了vector對象的容量和元素的初值。

如果用的是花括號,可以表述成我們想列表初始化(listinitialize)該vector對象。也就是說,初始化過程會盡可能地把花括號內的值當成是元素初始值的列表來處理,只有在無法執行列表初始化時才會考慮其他初始化方式。在上例中,給v2和v4提供的初始
值都能作為元素的值,所以它們都會執行列表初始化,vector對象v2包含一個元素而vector對象v4包含兩個元素。

另一方面,如果初始化時使用了花括號的形式但是提供的值又不能用來列表初始化,就要考慮用這樣的值來構造vector對象了。例如,要想列表初始化一個含有string對象的vector對象,應該提供能賦給string對象的初值。此時不難區分到底是要列表初始化vector對象的元素還是用給定的容量值來構造vector對象:

vector<string>v5{“hi“};      //列表初始化:v5有一個元素
vector<string>v6(“hi“);      //錯誤:不能使用字符串字面值構建vector對象
vector<string>v7{10};        //v7有10個默認初始化的元素
vector<string>V8{10,"hin1"}; //v8有10個值為vhi“的元素

盡管在上面的例子中除了第二條語句之外都用了花括號,但其實只有v5是列表初始化。要想列表初始化vector對象,花括號里的值必須與元素類型相同。顯然不能用int初始化string對象,所以v7和v8提供的值不能作為元素的初始值。確認無法執行列表初始化后,編譯器會嘗試用默認值初始化vector對象。

向vector對象中添加元素

對vector對象來說,直接初始化的方式適用于三種情況:初始值已知且數量較少、初始值是另一個vector對象的副本、所有元素的初始值都一樣。然而更常見的情況是:創建一個vectozr對象時并不清楚實際所需的元素個數,元素的值也經常無法確定。還有些時候即使元素的初值已知,但如果這些值總量較大而各不相同,那么在創建vector對象的時候執行初始化操作也會顯得過于煩瑣。

舉個例子,如果想創建一個vector對象令其包含從0到9共10個元素,使用列表初始化的方法很容易做到這一點;但如果vector對象包含的元素是從0到99或者從0到999呢?這時通過列表初始化把所有元素都一一羅列出來就不太合適了。對于此例來說,更好的處理方法是先創建一個空vector,然后在運行時再利用vector的成員函數push_back向其中添加元素。push_back負責把一個值當vector對象的尾元素“壓到(push)“vector對象的“尾端(back)“。例如:

vector<int>v2;//空vector對象
for(int i=0;i!=100;++i)v2.Push_back();//依次把整數值放到v2尾端//循環結束后v2有100個元素,值從0到99

在上例中,盡管知道vector對象最后會包含100個元素,但在一開始還是把它聲明成空vector,在每次迭代時才順序地把下一個整數作為v2的新元素添加給它。

同樣的,如果直到運行時才能知道vector對象中元素的確切個數,也應該使用剛剛這種方法創建vector對象并為其賦值。例如,有時需要實時讀入數據然后將其賦了vector對象:

//從標準輸入中讀取單詞,將其作為vector對象的元素存傅
string word;
vector<string> text;//空vector對象
while(cin>>word) {text.push_back(word);//把word添加到text后面
}

和之前的例子一樣,本例也是先創建一個宇vector,之后依次讀入未知數量的值并保存到text中。

關鍵概念:vector對象能高效增長

C++標準要求vector應該能在運行時高效快速地添加元素。因此既然vector對象能高效地增長,那么在定義vector對象的時候設定其大小也就沒什么必要了,事實上如果這么做性能可能更差。只有一種例外情況,就是所有(all)元素的值都一樣。一旦元素的值有所不同,更有效的辦法是先定義一個空的vector對象,再在運行時閉其中添加具體值。此外,vector還提供了方法,允許我們進一步提升動態添加元素的性能。

開始的時候創建空的vector對象,在運行時再動態添加元素,這一做法與C語言及其他大多數語言中內置數組類型的用法不同。特別是如果用慣了C或者Java,可以預計在創建vector對象時順便指定其容量是最好的。然而事實上,通常的情況是恰

向vector對象添加元素蘊含的編程假定

由于能高效便捷地向vector對象中添加元素,很多編程工作被極大簡化了。然而,這種簡便性也伴隨著一些對編寫程序更高的要求:其中一條就是必須要確保所寫的循環正確無誤,特別是在循環有可能改變vector對象容量的時候。

隨著對vector的更多使用,我們還會逐漸了解到其他一些隱含的要求,其中一條是現在就要指出的:如果循環體內部包含有向vector對象添加元素的語句,則不能使用范圍for循環。

WARNING:范圍for語句體內不應改變其所造歷序列的大小。

其他vector操作

除了push_back之外,vector還提供了幾種其他操作,大多數都和string的相關操作類似,表3.5列出了其中比較重要的一些。

表3.5:vector支持的操作

v.empty()如果v不含有任何元素,返回真;否則返回假
Y.sSize()返回v中元素的個數
Y.Push_back(t)向v的尾端添加一個值為t的元素
v[n]返回v中第n個位置上元素的引用
v1=v2用v2中元素的拷貝替換v1中的元素
vl={a,b,c…}用列表中元素的拷貝替換vl中的元素
vl==v2vl和v2相等當且僅當它們的元素數量相同東對應位置的元素值都相同
<,<=,>,>=顧名思義,以字典順序進行比較

訪問vector對象中元素的方法和訪問string對象中字符的方法差不多,也是通過元素在vector對象中的位置。例如,可以使用范圍for語句處理vector對象中的所有元素:

vector<int>V{112,3,4,5,6,718,917}
for(auto&:v)//對于中的每個元素(注意:i是一個引用)i*=i;//求元素值的平方
for(auto i:v)//對于中的每個元素
cout<<i<<" ";//輸出該元素
cout<<endl;

第一個循環把控制變量i定義成引用類型,這樣就能通過i給v的元素賦值,其中i的類型由auto關鍵字指定。這里用到了一種新的復合賦值運算符。如我們所知,+=把左側運算對象和右側運算對象相加,結果存入左側運算對象;類似的,*=把左側運算對象和右側運算對象相乘,結果存入左側運算對象。最后,第二個循環輸出所有元素。

vector的empty和size兩個成員與string的同名成功能完全一致:empty檢查vector對象是否包含元素然后返回一個布爾值;size則返回vector對象中元素的個數,返回值的類型是由vector定義的size_type類型。

各個相等性運算符和關系運算符也與string的相應運算符功能一致。兩個vector對象相等當且僅當它們所含的元素個數相同,而且對應位置的元素值也相同。關系運算符依照字典順序進行比較:如果兩個vector對象的容量不同,但是在相同位置上的元素值都一樣,則元素較少的vector對象小于元素較多的vector對象;若元素的值有區別,則vector對象的大小關系由第一對相異的元素值的大小關系決定。

只有當元素的值可比較時,vector對象才能被比較。一些類,如string等,確實定義了自己的相等性運算符和關系運算符。

計算vector內對象的索引

使用下標運算符能獲取到指定的元素。和string一樣,vector對象的下標也是從0開始計起,下標的類型是相應的size_type類型。只要vector對象不是一個常量,就能向下標運算符返回的元素賦值。此外,也能通過計算得到vector內對象的索引,然后直接獲取索引位置上的元素。

舉個例子,假設有一組成績的集合,其中成績的取值是從0到100。以10分為一個分數段,要求統計各個分數段各有多少個成績。顯然,從0到100總共有101種可能的成績取值,這些成績分布在11個分數段上:每10個分數構成一個分數段,這樣的分數段有10個,額外還有一個分數段表示滿分100分。這樣第一個分數段將統計成績在0到9之間的數量;第二個分數段將統計成績在10到19之間的數量,以此類推。最后一個分數段統計滿分100分的數量。

按照上面的描述,如果輸入的成績如下:

42 65 95 100 39 67 95 76 88 76 83 92 76 93

則輸出的結果應該是:

0 0 0 1 1 0 2 3 2 4 1

結果顯示:成績在30分以下的沒有、30分至39分有1個、40分至49分有1個、50分全59分沒有、60分至69分有2個、70分至79分有3個、80分至89分有2個、90分至99分有4個,還有1個是滿分。

在具體實現時使用一個含有11個元素的vector對象,每個元素分別用于統計各個分數段上出現的成績個數。對于某個成績來說,將其除以10就能得到對應的分數段索引。注意:兩個整數相除,結果還是整數,余數部分被自動忽略掉了。例如,42/10=4、65/10-6、100/10=10等。一旦計算得到了分數段索引,就能用它作為vector對象的下標,進而獲取該分數段的計數值并加1:

//以10分為一個分數段統計成績的數量:0~9,10~19,..,90~99,100
vector<unsigned> scores(11,0); //11個分數段,全都初始化為0
unsigned grade;
while(cin>>grade)//讀取成績if(grzade<=100)//只處理有效的成績++scores[grade/10];//將對應分數段的計數值加1

在上面的程序中,首先定義了一個vector對象存放各個分數段上成績的數量。此例中,由于初始狀態下每個元素的值都相同,所以我們為vector對象申請了11個元素,并把所有元素的初始值都設為0。while語句的條件部分負責讀入成績,在循環體內部首先檢查讀入的成績是否合法(即是否小于等于100分),如果合法,將成績對應的分數段的計數值加1。

執行計數值累加的那條語句很好地體現了C++程序代碼的簡潔性。表達式

++scores[grade/10];//將當前分數段的計數值加1

等價于

auto ind = grade/10;//得到分數段索引
scores[tnd]=scores[ind]+1;//將計數值加1

上述語句的含義是:用grade除以10來計算成績所在的分數段,然后將所得的結果作為變量scores的下標。通過運行下標運算獲取該分數段對應的計數值,因為新出現了一個屬于該分數段的成績,所以將計數值加1。

如前所述,使用下標的時候必須清楚地知道它是否在合理范圍之內。在這個程序里,我們事先確認了輸入的成績確實在0到100之間,這樣計算所得的下標就一定在0到10之間,屬于0到scores.size()-1規定的有效范圍,一定是合法的。

不能用下標形式添加元素

剛接觸C++語言的程序員也許會認為可以通過vector對象的下標形式來添加元素,事實并非如此。下面的代碼試圖為vector對象ivec添加10個元素:

vector<int>tvec;//空vector對象
for(decltype(ivec.size())ix = 0;ix!=10;++ix)ivec[ix]=ix;//嚴重錯誤:tvec不包吳任何元素

然而,這段代碼是錯誤的:ivec是一個空vector,根本不包含任何元素,當然也就不能通過下標去訪問任何元素!如前所述,正確的方法是使用push_bacK:

for(decltype(tvec.size())ix=0;ix!=10;++ix)ivec.push_back(ix); //正確:添加一個新元素,該元素的值是ix

vestor兌現(以及string對象)的下標運算答可用于訪問已存在的元素。而不能用于添加元素。

提示:只能對確知已存在的元素執行下標操作!

關于下標史須明確的一點是;只能對確知已存在的元素執行下標操作。例如,

vector<int>ivec;//空vector對象
cout<<ivec[013//錯誤:ivec不艮含任何元素vector<int>ivec2(10j);//含有10個元素的yector財象
cout<<ivec2[10];//錯誤:ivec2元素的合法索引是從0到9

試圖用下標的形式去訪問一個不存在的元素將引發錦誤,不過這種錯誤不會被編譯器發現,而是在運行時產生一個不可預知的值。

不幸的是,這種通過下標訪問不存在的元素的行為非常常見,而且會產生很嚴重的后果。所謂的緩沖區溢出(buffer overflow)指的就是這類錯誤,這也是導致PC及其他
設備上應用程序出現安全問題的一個重要原因。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67828.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67828.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67828.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Numpy核心編程攻略:Python數據處理、分析詳解與科學計算】2.6 廣播機制核心算法:維度擴展的數學建模

2.6 廣播機制核心算法&#xff1a;維度擴展的數學建模 目錄/提綱 #mermaid-svg-IfELXmhcsdH1tW69 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-IfELXmhcsdH1tW69 .error-icon{fill:#552222;}#mermaid-svg-IfELXm…

【Elasticsearch】硬件資源優化

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家&#xff0c;歷代文學網&#xff08;PC端可以訪問&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移動端可微信小程序搜索“歷代文學”&#xff09;總架構師&#xff0c;15年工作經驗&#xff0c;精通Java編…

bootstrap.yml文件未自動加載問題解決方案

在添加bootstrap.yml文件后,程序未自動掃描到,即圖標是這樣的: 查了一些資料,是缺少bootstrap相關依賴,雖然已經添加了spring-cloud-context依賴,但是這個依賴并未引入bootstrap依賴,可能是版本問題,需要手動引入 <dependency><groupId>org.springframework.cloud&…

C++底層學習預備:模板初階

文章目錄 1.編程范式2.函數模板2.1 函數模板概念2.2 函數模板原理2.3 函數模板實例化2.3.1 隱式實例化2.3.2 顯式實例化 2.4 模板參數的匹配原則 3.類模板希望讀者們多多三連支持小編會繼續更新你們的鼓勵就是我前進的動力&#xff01; 進入STL庫學習之前我們要先了解有關模板的…

【玩轉 Postman 接口測試與開發2_015】第12章:模擬服務器(Mock servers)在 Postman 中的創建與用法(含完整實測效果圖)

《API Testing and Development with Postman》最新第二版封面 文章目錄 第十二章 模擬服務器&#xff08;Mock servers&#xff09;在 Postman 中的創建與用法1 模擬服務器的概念2 模擬服務器的創建2.1 開啟側邊欄2.2 模擬服務器的兩種創建方式2.3 私有模擬器的 API 秘鑰的用法…

【算法】回溯算法專題③ ——排列型回溯 python

目錄 前置小試牛刀回歸經典舉一反三總結 前置 【算法】回溯算法專題① ——子集型回溯 python 【算法】回溯算法專題② ——組合型回溯 剪枝 python 小試牛刀 全排列 https://leetcode.cn/problems/permutations/description/ 給定一個不含重復數字的數組 nums &#xff0c;返…

8.原型模式(Prototype)

動機 在軟件系統中&#xff0c;經常面臨著某些結構復雜的對象的創建工作&#xff1b;由于需求的變化&#xff0c;這些對象經常面臨著劇烈的變化&#xff0c;但是它們卻擁有比較穩定一致的接口。 之前的工廠方法和抽象工廠將抽象基類和具體的實現分開。原型模式也差不多&#…

LabVIEW如何高頻采集溫度數據?

在LabVIEW中進行高頻溫度數據采集時&#xff0c;選擇合適的傳感器&#xff08;如熱電偶或熱電阻&#xff09;和采集硬件是關鍵。下面是一些建議&#xff0c;幫助實現高效的溫度數據采集&#xff1a; 1. 傳感器選擇&#xff1a; 熱電偶&#xff08;Thermocouple&#xff09;&am…

Kotlin 委托詳解

Kotlin 委托詳解 引言 Kotlin 作為一種現代化的編程語言&#xff0c;在 Android 開發等領域得到了廣泛的應用。在 Kotlin 中&#xff0c;委托&#xff08;Delegation&#xff09;是一種強大的特性&#xff0c;它可以讓我們以更簡潔的方式實現代碼的復用和擴展。本文將詳細解析…

npm 和 pip 安裝中常見問題總結

安裝路徑的疑惑&#xff1a;NPM 和 PIP 的安裝機制 NPM 安裝路徑規則&#xff1a; 依賴安裝在項目目錄下&#xff1a; 當你運行 npm install --save-dev jest&#xff0c;它會在當前目錄&#xff08;例如 F:\&#xff09;下創建一個 node_modules 文件夾&#xff0c;把 jest 安…

人工智能:農業領域的變革力量

在當今科技飛速發展的時代&#xff0c;人工智能正以前所未有的態勢滲透進各個領域&#xff0c;農業也不例外。想象一下&#xff0c;未來的農田里&#xff0c;農民不再是彎腰勞作的形象&#xff0c;而是坐在高科技的“智能農場”里&#xff0c;悠閑地喝著咖啡&#xff0c;指揮著…

LLM的Deep Research功能:重構人類認知與創新的新范式

在人工智能迅速發展的今天&#xff0c;大語言模型&#xff08;LLM&#xff09;的deep research功能正在成為重構人類認知方式的關鍵力量。 這一突破性的技術進展不僅帶來了工具層面的革新&#xff0c;更深刻地觸及了人類認知能力的本質。 本文將從認知科學的視角出發&#xf…

【Cadence仿真技巧學習筆記】求解65nm庫晶體管參數un, e0, Cox

在設計放大器的第一步就是確定好晶體管參數和直流工作點的選取。通過閱讀文獻&#xff0c;我了解到L波段低噪聲放大器的mos器件最優寬度計算公式為 W o p t . p 3 2 1 ω L C o x R s Q s p W_{opt.p}\frac{3}{2}\frac{1}{\omega LC_{ox}R_{s}Q_{sp}} Wopt.p?23?ωLCox?Rs…

前端力扣刷題 | 6:hot100之 矩陣

73. 矩陣置零 給定一個 m x n 的矩陣&#xff0c;如果一個元素為 0 &#xff0c;則將其所在行和列的所有元素都設為 0 。請使用 原地 算法。 法一&#xff1a; var setZeroes function(matrix) {let setX new Set(); // 用于存儲需要置零的行索引let setY new Set(); //…

每日一題——有效括號序列

有效括號序列 題目描述數據范圍&#xff1a;復雜度要求&#xff1a; 示例題解代碼實現代碼解析1. 定義棧和棧操作2. 棧的基本操作3. 主函數 isValid4. 返回值 時間和空間復雜度分析 題目描述 給出一個僅包含字符 (, ), {, }, [, ] 的字符串&#xff0c;判斷該字符串是否是一個…

集合通訊概覽

&#xff08;1&#xff09;通信的算法 是根據通訊的鏈路組成的 &#xff08;2&#xff09;因為通信鏈路 跟硬件強相關&#xff0c;所以每個CCL的庫都不一樣 芯片與芯片、不同U之間是怎么通信的&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 很重要…

紅黑樹的封裝

一、封裝思路 在 STL 中 map set 的底層就是封裝了一棵紅黑樹。 其中連接紅黑樹和容器的是迭代器&#xff0c;map set 暴露出的接口都不是自己寫的&#xff0c;而是紅黑樹寫的&#xff0c;外部接口封裝紅黑樹接口。 所以寫出紅黑樹為 map set 寫的接口&#xff0c;再在上層的…

java異常處理——try catch finally

單個異常處理 1.當try里的代碼發生了catch里指定類型的異常之后&#xff0c;才會執行catch里的代碼&#xff0c;程序正常執行到結尾 2.如果try里的代碼發生了非catch指定類型的異常&#xff0c;則會強制停止程序&#xff0c;報錯 3.finally修飾的代碼一定會執行&#xff0c;除…

使用QMUI實現用戶協議對話框

使用QMUI實現用戶協議對話框 懶加載用于初始化 TermServiceDialogController 對象。 懶加載 lazy var 的作用 lazy var dialogController: TermServiceDialogController {let r TermServiceDialogController()r.primaryButton.addTarget(self, action: #selector(primaryC…

C++進階: 紅黑樹及map與set封裝

紅黑樹總結整理 紅黑色概述&#xff1a; 紅黑樹整理與AVL樹類似&#xff0c;但在對樹的平衡做控制時&#xff0c;AVL樹會比紅黑樹更嚴格。 AVL樹是通過引入平衡因子的概念進行對樹高度控制。 紅黑樹則是對每個節點標記顏色&#xff0c;對顏色進行控制。 紅黑樹控制規則&…