C++——STL——容器deque(簡單介紹),適配器——stack,queue,priority_queue

目錄

1.deque(簡單介紹)

1.1?deque介紹:

1.2?deque迭代器底層

1.2.1 那么比如說用迭代器實現元素的遍歷,是如何實現的呢?

1.2.2?頭插

1.2.3?尾插

1.2.4?實現+=

??編輯

1.2.5?總結

2.stack

2.1?函數介紹

2.2?模擬實現:

3.queue

3.1?函數介紹

3.2?模擬實現:

3.3?為什么選擇deque來作為他們的底層容器?

4.priority_queue

4.1 priority_queue的使用

4.2?仿函數

4.2.1?基本原理

4.3?priority_queue模擬實現

5.cpu緩存知識


1.deque(簡單介紹)

咱們今天講適配器以及deque,主要講適配器,那么講deque是因為,stack,queue的底層都是封裝的容器deque。

?

Container就是適配器,可以看出,官方庫中都是以deque為底層容器,那么為什么呢?今天咱們就來討論一下。

deque與queue看著是不是很像,但千萬別把他們給搞混了,deque是容器,而queue是容器適配器。?

1.1?deque介紹:

deque(雙端隊列):是一種雙開口的"連續"空間的數據結構,雙開口的含義是:可以在頭尾兩端 進行插入和刪除操作,且時間復雜度為O(1),與vector比較,頭插效率高,不需要搬移元素;與 list比較,空間利用率比較高。它支持兩端的高效插入與刪除。

?deque的功能也挺齊全的其實,基本上前面幾個容器有的,它都具備。

  • 核心操作

    • push_back()?和?push_front():在兩端插入元素。

    • pop_back()?和?pop_front():在兩端刪除元素。

    • operator[]?或?at():隨機訪問元素。

    • front()?和?back():訪問兩端元素。

那么接下來咱們呢進入重點部分,也就是deque的迭代器部分的講解,聽完這個,您就知道為什么stack與queue要選擇deque作為他們的底層容器了。

1.2?deque迭代器底層

?

deque的迭代器更像是一塊一塊的動態內存塊。例如上圖,右方的就是他的一個一個的內存塊,也可以叫緩沖區,那么這些內存塊是由中間的那個中控指針數組map控制的。map中存的是指向每個內存塊的指針,那么它們要是想移動內存塊的時候,就只需要移動指向他們的指針即可。

當然,這個也需要擴容,但是只需要當中控數組滿了的時候才去擴容,即擴容的對象就單一了。

?

這個圖更形象,因為這個圖中有控制每一個內存塊的迭代器。注意看,這個迭代器中有node,這個node是個二級指針,指向中控器中的元素(一級指針)。所以,內存塊的移動就是對node進行的加加或者減減。那么cur指向的是當前元素的位置,而first指向的是開始,last指向的是結尾。

1.2.1 那么比如說用迭代器實現元素的遍歷,是如何實現的呢?

?

咱們來看這一段代碼,比較兩個內存塊是否相等,比較cur即可,因為每個內存塊的first與last的位置都是相同的,所以無法比較這兩個,只有比較你當前元素的位置才可以看出你兩個內存塊到底相不相等。這里面也是實現的operator++,

1.先讓每一個塊中的cur往后走,直至走完?。

2.如果說當前塊中的元素遍歷完了(cur==last),那么通過node來改變下一個要訪問的內存塊,之后更新first,last,cur的位置即可。

3.以此類推即可。

4.那么是不是可以看出遍歷的時候,deque的迭代器要頻繁的去檢測其 是否移動到某段小空間的邊界(cur==last),導致效率低下。所以說deque并不適合遍歷。

1.2.2?頭插

頭插直接在map前面拿一個內存塊,在后面插入數據即可,但之后別忘了更新位置。則,頭插既不需要申請空間(因為map已有空間),也不需要反復挪動數據,很高效吧。

1.2.3?尾插

注意頭插是從尾部開始插入,尾插是從頭部開始插入,那么這里需要注意的是,cur在這里指向的當前元素的下一個位置,是因為,咱們的迭代器都是左閉右開的,所以說,左邊的可以cur可以指向當前元素(頭插),因為可以取到那個數據。但是右邊的cur指向的當前元素的下一個位置(尾插),這樣才可以確保可以取到已經插入的那個元素。

但尾插也是很高效的。因為他也是不需要申請空間,直接從map中拿就可以了。

1.2.4?實現+=

?

現在比如說咱們要加等一個數,那么面臨的問題是跳過幾個內存塊?最后的位置要落在最后一個內存塊的哪個位置?那么接下來,用除(/)去確定跳過幾個內存塊,用取模(%)去確定最后停在內存塊的第幾個位置處,您想想是不是這樣的一個道理。當然這個只是簡單的原理,具體的實現,比較復雜,?因為考慮了負數。

1.2.5?總結

OK,經過以上的講解,大家應該知道deque的迭代器不適合用于遍歷元素,因為需要頻繁的判斷邊界是否相等。

所以,deque的缺陷:

1.與vector比較,deque的優勢是:頭部插入和刪除時,不需要搬移元素,效率特別高,而且在擴 容時,也不需要搬移大量的元素,因此其效率是必vector高的。

2.與list比較,其底層是連續空間,空間利用率比較高,不需要存儲額外字段。

3.但是,deque有一個致命缺陷:不適合遍歷,因為在遍歷時,deque的迭代器要頻繁的去檢測其 是否移動到某段小空間的邊界,導致效率低下,而序列式場景中,可能需要經常遍歷,因此在實 際中,需要線性結構時,大多數情況下優先考慮vector和list,deque的應用并不多,而目前能看 到的一個應用就是,STL用其作為stack和queue的底層數據結構。

?咱們先來看stack與queue,最后再來說為什么選擇deque作為底層容器,因為還得理解stack與queue的模擬實現。

2.stack

stack是個容器適配器,這是個新的概念,那么什么是容器適配器呢?容器適配器是建立在現有容器之上的抽象,提供不同的接口,但底層使用已有的容器實現。以我的個人見解就是這些stack,queue,priority_queue,這些的接口可以用其他的容器進行覆蓋,就是說,這些容器適配器有的接口,那些對應的底層容器也是有的,這樣就直接將那些底層容器封裝起來,然后再實現一些這些容器適配器特有的接口,其實也是一種封裝的體現。

即將底層的那些大的不同的封裝起來,不讓你看,讓你看的就是那些自己的接口,這樣雖然底層可能用不同的容器實現的,但是你表面看上去還是沒什么不同,但是底層早已天差地別。這就是封裝,不關心底層的實現,只關心自己的目前的接口。

2.1?函數介紹

stack():構造空的棧.

empty():檢測stack是否為空.

size():返回stack中元素的個數.

top():返回棧頂元素的引用.

push():將元素val壓入stack中.

pop():將stack中尾部的元素彈出.

這些看著是不是很眼熟,沒錯,就是咱們數據結構——棧和隊列那一章實現的。

2.2?模擬實現:

template<class T, class Container = deque<T>>

class stack

{

????????public:

????????void push(const T& x)

????????{

????????????????_con.push_back(x);

????????}

????????void pop()

????????{

????????????????_con.pop_back();

????????}

????????T& top()

?????????{

????????????????return _con.back();

????????}

????????const T& top() const

????????{

????????????????return _con.back();

????????}

????????bool empty() const

????????{

????????????????return _con.empty();

????????}

????????size_t size() const

????????{

????????????????return _con.size();

????????}

????????private:

????????Container _con;//用模板去實例化對象,這樣_con可以是任何類的對象。

};

基本也就這些東西,唯一增加的就是一個容器適配器。

3.queue

1. 隊列是一種容器適配器,專門用于在FIFO上下文(先進先出)中操作,其中從容器一端插入元 素,另一端提取元素。

2. 隊列作為容器適配器實現,容器適配器即將特定容器類封裝作為其底層容器類,queue提供 一組特定的成員函數來訪問其元素。元素從隊尾入隊列,從隊頭出隊列。

3. 底層容器可以是標準容器類模板之一,也可以是其他專門設計的容器類。該底層容器應至少 支持以下操作:

empty:檢測隊列是否為空

size:返回隊列中有效元素的個數

front:返回隊頭元素的引用

back:返回隊尾元素的引用

push_back:在隊列尾部入隊列

pop_front:在隊列頭部出隊列

4. 標準容器類deque和list滿足了這些要求。默認情況下,如果沒有為queue實例化指定容器類,則使用標準容器deque。

3.1?函數介紹

queue():構造空的隊列

empty():檢測隊列是否為空,是返回true,否則返回false

size():返回隊列中有效元素的個數

front():返回隊頭元素的引用

back():返回隊尾元素的引用

push():在隊尾將元素val入隊列

pop():將隊頭元素出隊列

3.2?模擬實現:

template<class T, class Container = deque<T>>

class queue

{

????????public:

????????void push(const T& x)

????????{

????????????????_con.push_back(x);

????????}

????????void pop()

????????{

????????????????_con.pop_front();

????????}

????????T& front()

????????{

????????????????return _con.front();

????????}

????????const T& front() const

????????{

????????????????return _con.front();

????????}

????????T& back()

????????{

????????????????return _con.back();

????????}

????????const T& back() const

????????{

????????????????return _con.back();

????????}

????????bool empty() const

????????{

????????????????return _con.empty();

????????}

????????size_t size() const

????????{

????????????????return _con.size();

????????}

????????private:

????????Container _con;

};

3.3?為什么選擇deque來作為他們的底層容器?

stack是一種后進先出的特殊線性數據結構,因此只要具有push_back()和pop_back()操作的線性 結構,都可以作為stack的底層容器,比如vector和list都可以;queue是先進先出的特殊線性數據 結構,只要具有push_back和pop_front操作的線性結構,都可以作為queue的底層容器,比如 list。但是STL中對stack和queue默認選擇deque作為其底層容器,主要是因為:

1. stack和queue不需要遍歷(因此stack和queue沒有迭代器),只需要在固定的一端或者兩端進 行操作。而經過咱們上邊對deque迭代器原理的講解,可知頭插與尾插的效率很高。

2. 在stack中元素增長時,deque比vector的效率高(擴容時不需要搬移大量數據);queue中的 元素增長時,deque不僅效率高,而且內存使用率高。 結合了deque的優點,而完美的避開了其缺陷。?

4.priority_queue

1. 優先隊列是一種容器適配器,根據嚴格的弱排序標準,它的第一個元素總是它所包含的元素 中最大的

2. 此上下文類似于堆,在堆中可以隨時插入元素,并且只能檢索最大堆元素(優先隊列中位于頂 部的元素)。

3. 優先隊列被實現為容器適配器,容器適配器即將特定容器類封裝作為其底層容器類,queue 提供一組特定的成員函數來訪問其元素。元素從特定容器的“尾部”彈出,其稱為優先隊列的 頂部。

4. 底層容器可以是任何標準容器類模板,也可以是其他特定設計的容器類。容器應該可以通過 隨機訪問迭代器訪問,并支持以下操作:

empty():檢測容器是否為空

size():返回容器中有效元素個數

front():返回容器中第一個元素的引用

push_back():在容器尾部插入元素

pop_back():刪除容器尾部元素?

?5. 標準容器類vector和deque滿足這些需求。默認情況下,如果沒有為特定的priority_queue 類實例化指定容器類,則使用vector。

6. 需要支持隨機訪問迭代器,以便始終在內部保持堆結構。容器適配器通過在需要時自動調用 算法函數make_heap、push_heap和pop_heap來自動完成此操作。

這里的底層容器又變了,是vector,那么問什么是vector呢?因為priority_queue的底層是堆,而堆又是以順序表為載體實現的(后面會講)。所以說具體的原因是:

1. vector的連續內存布局,訪問元素高效,緩存友好。

2. 尾部操作(push_back和pop_back)的高效性,這對堆的調整非常重要。

3. 動態擴容的均攤時間復雜度低。

4. 相比其他容器如deque或list,vector在堆操作中的綜合性能更好。

4.1 priority_queue的使用

優先級隊列默認使用vector作為其底層存儲數據的容器,在vector上又使用了堆算法將vector中 元素構造成堆的結構,因此priority_queue就是堆,所有需要用到堆的位置,都可以考慮使用 priority_queue。注意:默認情況下priority_queue是大堆。如果想用小頂堆,就需要傳入greater<T>這個仿函數。

priority_queue()/[riority_queue(first,last):構造一個空的優先級隊列

empty():檢測優先級隊列是否為空,是返回true,否則返回false

top():返回優先級隊列中最大(最小元素),即堆頂元素

push(x):在優先級隊列中插入元素x

pop():刪除優先級隊列中最大(最小)元素,即堆頂元素

在看他的模擬實現之前,先學一個知識點:仿函數

4.2?仿函數

在 C++ 中,仿函數(Functor)?是一種通過重載?operator()?運算符,使得類的對象可以像函數一樣被調用的機制。它是 STL(標準模板庫)中實現自定義行為的核心工具之一,常用于算法(如?sorttransform)和容器(如?priority_queueset)的自定義邏輯中。

4.2.1?基本原理

仿函數本質是一個類對象,但通過重載?operator(),可以像函數一樣調用:

例如:

class Adder {
public:int operator()(int a, int b) {return a + b;}
};int main() {Adder add;cout << add(3, 5); // 輸出 8:對象像函數一樣被調用
}

仿函數與普通函數的比較:?

特性仿函數普通函數
狀態管理可以保存狀態(通過成員變量)無狀態(全局變量除外)
靈活性可作為模板參數傳遞需用函數指針或?std::function
性能通常可被編譯器內聯優化函數指針可能無法內聯
適配性與 STL 算法/容器無縫集成需額外適配(如?std::ptr_fun

現在仿函數用到的還比較少,因為博主現在看的關于仿函數的代碼比較少。那么如何創建一個仿函數呢?

  1. 定義類:創建一個類,重載?operator()

  2. 實現邏輯:在?operator()?中定義具體行為。

  3. 傳遞對象:將類的實例傳遞給算法或容器。

?OK,仿函數目前就講這么多,接下來來看代碼就可以看的懂了。

4.3?priority_queue模擬實現

template<class T>
class less
{
public:
?? ?bool operator()(const T & s1, const T & s2)//仿函數重載的是(),不是其他的符號
?? ?{
?? ??? ?return s1 < s2;
?? ?}
};
/*template<class T>
class less<T*>
{
public:
?? ?bool operator()( T &*const s1, ?T & *const s2)
?? ?{
?? ??? ?return *s1 < *s2;
?? ?}
};*/這個注釋掉了
template<class T>
class greater
{
public:
?? ?bool operator()(const T & s1, const T & s2)
?? ?{
?? ??? ?return s1 > s2;
?? ?}
};
template<class T, class Container = vector<T>, class Compare = less<T>>
//為什么在test.cpp中放開#include"priority_queue.h",vector就可以用了呢?
class priority_queue
{
public:
?? ?priority_queue()//一個類創建好了,別忘了構造
?? ?{}
?? ?void push(const T& x)
?? ?{
?? ??? ?_con.push_back(x);
?? ??? ?//底層是堆,所以不管插入還是刪除數據,最后都別忘了再調整
?? ??? ?adjustup(_con.size() - 1);
?? ?}
?? ?void pop()
?? ?{
?? ??? ?swap(_con[0], _con[_con.size() - 1]);

?? ??? ?_con.pop_back();

?? ??? ?adjustdown(0);

?? ?}
?? ?const T& top() const//這倆const是必須要加的,因為堆頂的元素是不允許
?? ??? ?//被更改的,一旦更改,就全都亂了,堆中元素的順序全都亂了
?? ?{
?? ??? ?return _con[0];
?? ?}
?? ?size_t size() const//這個返回的是個數,是size類型,不是T類型
?? ?{
?? ??? ?return _con.size();
?? ?}
?? ?bool empty()
?? ?{
?? ??? ?return _con.empty();
?? ?}
private:
?? ?void adjustup(int child)//parent=(child-1)/2
?? ??? ?//從誰開始調整,就傳誰,這里先從孩子開上調整,所以先傳孩子
?? ?{
?? ??? ?Compare com;
?? ??? ?int parent = (child - 1) / 2;
?? ??? ?while (child > 0)
?? ??? ?{
?? ??? ??? ?if (com( _con[parent], _con[child] ))
?? ??? ??? ?{
?? ??? ??? ??? ?swap(_con[child], _con[parent]);
?? ??? ??? ??? ?child = parent;
?? ??? ??? ??? ?parent = (child - 1) / 2;
?? ??? ??? ?}
?? ??? ??? ?else
?? ??? ??? ?{
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?void adjustdown(int parent)
?? ?{
?? ??? ?Compare com;
?? ??? ?size_t child = parent * 2 + 1;
?? ??? ?while (child < _con.size())
?? ??? ?{
?? ??? ??? ?if (child + 1 < _con.size() && com(_con[child] , _con[child + 1]))
?? ??? ??? ?{
?? ??? ??? ??? ?child += 1;
?? ??? ??? ?}
?? ??? ??? ?if (com( _con[parent], _con[child] ))//這個地方是<,return x<y,所以注意com中的順序
?? ??? ??? ?{
?? ??? ??? ??? ?swap(_con[child], _con[parent]);
?? ??? ??? ??? ?parent = child;
?? ??? ??? ??? ?child = parent * 2 + 1;
?? ??? ??? ?}
?? ??? ??? ?else
?? ??? ??? ?{
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ?}
?? ?}
private:
?? ?Container _con;
};

這里就不放代碼圖片了,因為截圖的話,一整張字太小,看不清代碼。?

?

這里還要注意的是包的頭文件,一般像這樣的#include""的頭文件放在using?namespace?std;后

,這樣可以避免出現錯誤。

OK,以上關于三個容器適配器的內容講完了,其實您看,也就多了一個容器適配器,以及模板,其余的用法啥的與前面的?容器基本類似。主要這部分還是在多寫代碼多應用,我在這嘴皮子磨冒煙了,您不寫代碼,還是沒用。

5.cpu緩存知識

上面咱們老是提到緩存命中率高,啥的,這個到底是啥,那么今天我就來簡單的介紹一下:

假如說有一段數據,那么這個數據是不是存放在內存中,當然也有的存放在緩存中。如果說cpu要訪問一個數據,要看這個數據是否在緩存中,在就叫緩存命中,不在就叫緩存不命中。不命中,就要先將數據從內存加載到緩存中(一般都是加載一段數據)。然后再訪問緩存。

?

OK,咱們先來看vector,為什么說vector的緩存命中率高呢?

假如說第一個數據不在緩存中,那么cpu就要讀取一段數據到緩存中,又因為vector地址是連續的,所以說讀一段數據到緩存中就很自然地將后面的數據全都讀到緩存中并且全部讀取出來。

但是list:緩存命中率低

它的地址不是連續的,所以說你讀取一段數據的時候,可能讀過來了,數據不是咱們想要的?。還可能讀過來了,但不是咱們想要的數據,這就是緩存污染!

OK,本博主的粗略解釋就這些,大家要是想看詳細的。

與程序員相關的CPU緩存知識 | 酷 殼 - CoolShell

這是陳大佬寫的一篇文章,大家可以去閱讀一下。

本篇完...................

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

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

相關文章

Java并發編程-線程池

Java并發編程-線程池 線程池運行原理線程池生命周期線程池的核心參數線程池的阻塞隊列線程池的拒絕策略線程池的種類newFixedThreadPoolnewSingleThreadExecutornewCachedThreadPoolnewScheduledThreadPool 創建線程池jdk的Executors(不建議&#xff0c;會導致OOM)jdk的ThreadP…

【前沿】成像“跨界”測量——掃焦光場成像

01 背景 眼睛是人類認識世界的重要“窗口”&#xff0c;而相機作為眼睛的“延伸”&#xff0c;已經成為生產生活中最常見的工具之一&#xff0c;廣泛應用于工業檢測、醫療診斷與影音娛樂等領域。傳統相機通常以“所見即所得”的方式記錄場景&#xff0c;傳感器捕捉到的二維圖像…

TM1640學習手冊及示例代碼

數據手冊 TM1640數據手冊 數據手冊解讀 這里我們看管腳定義DIN和SCLK&#xff0c;一個數據線一個時鐘線 SEG1~SEG8為段碼&#xff0c;GRID1~GRID16為位碼&#xff08;共陰極情況下&#xff09; 這里VDD給5V 數據指令 數據命令設置 地址命令設置 顯示控制命令 共陰極硬件連接圖…

uni-app 開發企業級小程序課程

課程大小&#xff1a;7.7G 課程下載&#xff1a;https://download.csdn.net/download/m0_66047725/90616393 更多資源下載&#xff1a;關注我 備注&#xff1a;缺少兩個視頻5-14 tabs組件進行基本的數據展示和搜索歷史 處理searchData的刪除操作 1-1導學.mp4 2-10小程序內…

判斷點是否在多邊形內

代碼段解析: const intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); 第一部分:(yi > y) !== (yj > y) 作用:檢查點 (x,y) 的垂直位置是否跨越多邊形的當前邊。 yi > y 和 yj > y 分別檢查邊的兩個端…

【redis】集群 如何搭建集群詳解

文章目錄 集群搭建1. 創建目錄和配置2. 編寫 docker-compose.yml完整配置文件 3. 啟動容器4. 構建集群超時 集群搭建 基于 docker 在我們云服務器上搭建出一個 redis 集群出來 當前節點&#xff0c;主要是因為我們只有一個云服務器&#xff0c;搞分布式系統&#xff0c;就比較…

[langchain教程]langchain03——用langchain構建RAG應用

RAG RAG過程 離線過程&#xff1a; 加載文檔將文檔按一定條件切割成片段將切割的文本片段轉為向量&#xff0c;存入檢索引擎&#xff08;向量庫&#xff09; 在線過程&#xff1a; 用戶輸入Query&#xff0c;將Query轉為向量從向量庫檢索&#xff0c;獲得相似度TopN信息將…

C語言復習筆記--字符函數和字符串函數(下)

在上篇我們了解了部分字符函數及字符串函數,下面我們來看剩下的字符串函數. strstr 的使用和模擬實現 老規矩,我們先了解一下strstr這個函數,下面看下這個函數的函數原型. char * strstr ( const char * str1, const char * str2); 如果沒找到就返回NULL指針. 下面我們看下它的…

FreeRTOS中的優先級翻轉問題及其解決方案:互斥信號量詳解

FreeRTOS中的優先級翻轉問題及其解決方案&#xff1a;互斥信號量詳解 在實時操作系統中&#xff0c;任務調度是基于優先級的&#xff0c;高優先級任務應該優先于低優先級任務執行。但在實際應用中&#xff0c;有時會出現"優先級翻轉"的現象&#xff0c;嚴重影響系統…

深度學習-全連接神經網絡

四、參數初始化 神經網絡的參數初始化是訓練深度學習模型的關鍵步驟之一。初始化參數&#xff08;通常是權重和偏置&#xff09;會對模型的訓練速度、收斂性以及最終的性能產生重要影響。下面是關于神經網絡參數初始化的一些常見方法及其相關知識點。 官方文檔參考&#xff1…

GIS開發筆記(9)結合osg及osgEarth實現三維球經緯網格繪制及顯隱

一、實現效果 二、實現原理 按照5的間隔分別創建經緯線的節點,掛在到組合節點,組合節點掛接到根節點。可以根據需要設置間隔度數和線寬、線的顏色。 三、參考代碼 //創建經緯線的節點 osg::Node *GlobeWidget::createGraticuleGeometry(float interval, const osg::Vec4 …

《Relay IR的基石:expr.h 中的表達式類型系統剖析》

TVM Relay源碼深度解讀 文章目錄 TVM Relay源碼深度解讀一 、從Constant看Relay表達式的設計哲學1. 類定義概述2. ConstantNode 詳解1. 核心成員2. 關鍵方法3. 類型系統注冊 3. Constant 詳解1. 核心功能 二. 核心內容概述(1) Relay表達式基類1. RelayExprNode 和 RelayExpr 的…

自動駕駛地圖數據傳輸協議ADASIS v2

ADASIS&#xff08;Advanced Driver Assistance Systems Interface Specification&#xff09;直譯過來就是 ADAS 接口規格&#xff0c;它要負責的東西其實很簡單&#xff0c;就是為自動駕駛車輛提供前方道路交通相關的數據&#xff0c;這些數據被抽象成一個標準化的概念&#…

Flutter 狀態管理 Riverpod

Android Studio版本 Flutter SDK 版本 將依賴項添加到您的應用 flutter pub add flutter_riverpod flutter pub add riverpod_annotation flutter pub add dev:riverpod_generator flutter pub add dev:build_runner flutter pub add dev:custom_lint flutter pub add dev:riv…

【EasyPan】MySQL主鍵與索引核心作用解析

【EasyPan】項目常見問題解答&#xff08;自用&持續更新中…&#xff09;匯總版 MySQL主鍵與索引核心作用解析 一、主鍵&#xff08;PRIMARY KEY&#xff09;核心作用 1. 數據唯一標識 -- 創建表時定義主鍵 CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,use…

IcePlayer音樂播放器項目分析及學習指南

IcePlayer音樂播放器項目分析及學習指南 項目概述 IcePlayer是一個基于Qt5框架開發的音樂播放器應用程序&#xff0c;使用Visual Studio 2013作為開發環境。該項目實現了音樂播放、歌詞顯示、專輯圖片獲取等功能&#xff0c;展現了桌面應用程序開發的核心技術和設計思想。 技…

vscode 打開新頁簽

目錄 vscode 打開新頁簽 完整settings.json內容&#xff1a; vscode 打開新頁簽 .vscode目錄中 新建settings.json 在 settings.json 文件中&#xff0c;添加或修改以下行&#xff1a; json "workbench.editor.enablePreview": false 這將禁用預覽模式&#xff0…

C語言高頻面試題——常量指針與指針常量區別

1. 常量指針&#xff08;Pointer to Constant&#xff09; 定義&#xff1a; 常量指針是指向一個常量數據的指針&#xff0c;即指針指向的內容不能通過該指針被修改。 語法&#xff1a; const int* ptr;或者&#xff1a; int const* ptr;解釋&#xff1a; const修飾的是指…

c++基礎·列表初始化

目錄 一、列表初始化的核心優勢 二、基礎數據類型與數組初始化 1. 基礎類型初始化 2. 數組初始化 三、類與結構體初始化 1. 構造函數匹配規則 2. 注意事項 四、標準容器初始化 五、聚合類型&#xff08;Aggregate Types&#xff09;初始化 1. 聚合類型定義 2. 初始化…

數據分析與產品、運營、市場之間如何有效對齊

數據分析的重要性在于它能夠將海量的原始信息轉化為可操作的洞察。以產品開發為例,通過用戶行為數據的分析,產品經理可以清晰了解哪些功能被頻繁使用,哪些設計導致用戶流失,從而優化迭代方向。運營團隊則依靠數據分析來監控供應鏈效率、預測需求波動,甚至通過實時數據調整…