C++:類和對象(從底層編譯開始)詳解[前篇]

目錄

一.inline內聯的詳細介紹

(1)為什么在調用內聯函數時不需要建立棧幀:

(2)為什么inline聲明和定義分離到兩個文件會產生鏈接錯誤,鏈接是什么,為什么沒有函數地址:

二.類,實例化和this指針

1.類的介紹(class):

2.實例化:

(1)實例化的概念:

(2)實例化的空間分配:

3.this指針:

4.關于空指針訪問成員變量的注意點:

三.類的默認成員函數

1.構造函數:

2.析構函數:

3.拷貝構造函數:

4.運算符重載:

四.日期類實現

一.inline內聯的詳細介紹

為了更清楚的明白類的定義與底層運行邏輯,我先從inline內聯開始講起:

? ?inline修飾的函數叫做內聯函數編譯時C++編譯器會在調用的地方展開內聯函數,這樣調用內聯函數就不需要建立棧幀了,就可以提高效率 //(1)為什么不需要建立棧幀

? inline對于編譯器??只是?個建議,也就是說,你加了inline編譯器也可以選擇在調?的地方不展開,不同編譯器關于inline什么情況展開各不相同,因為C++標準沒有規定,inline適用于頻繁調?的短?函數,對于遞歸函數,代碼相對多?些的函數,加上inline也會被編譯器忽略(因為內聯的展開在需要頻繁調用短小函數的代碼里,可以大限度上減少函數調用指令(call)的使用,而在其他函數體本身較大的情況下,inline不展開的調用指令的方法可能會顯得更為簡便)?

? C語言實現宏函數也會在預處理時替換展開,但是宏函數實現很復雜很容易出錯的,且不?便調 試,C++設計了inline?的就是替代C的宏函數

? vs編譯器debug版本下?默認是不展開inline的,這樣方便調試

? inline不建議聲明和定義分離到兩個?件,分離會導致鏈接錯誤。因為inline被展開,就沒有函數地址,鏈接時會出現報錯//(2)為什么會產生鏈接錯誤,鏈接是什么,為什么沒有函數地址

(內聯的使用示例)

#include <iostream>// 顯式聲明為內聯函數
inline int add(int a, int b) {return a + b;
}int main() {std::cout << add(3, 5) << std::endl; // 編譯器可能將 add(3,5) 展開為 `3 + 5`return 0;
}

上述的闡述乍看總有種似懂非懂的感覺,但一旦深入想想就還有好些東西不明不白,下面我將對這段話中可能會產生的疑問做出一一解答:

(1)為什么在調用內聯函數時不需要建立棧幀:

(a).在理解這個問題之前,我們需要先搞明白函數的棧幀是怎么一回事

? ? ? ?簡而言之棧幀是程序執行過程中用于保存函數調用狀態的臨時數據結構,它在函數調用時被創建,返回時銷毀。每個棧幀對應一次函數調用,記錄了函數的執行上下文信息

以下這張圖片就展示了函數Add在調用時所創建的棧幀,而其中的push等相關匯編命令我也附在下面:

? ? ? ??

(b).再讓我們區別以下函數的棧幀整體代碼的編譯和鏈接的關系:

據上述代碼編譯的過程而言,函數棧幀的創建屬于程序運行時的動態數據結構,雖與編譯鏈接過程的靜態代碼無關,但編譯與鏈接依舊會在其運行時對其產生影響:如編譯階段為棧幀的創建和銷毀生成正確的指令,以及鏈接階段確定函數的位置以及符號引用,因此,一般情況下較小的函數被inline展開時,其函數名并不會進入符號表,而是直接在調用處替換代碼(發生在預處理中,編譯之前),自然也就跟棧幀的創建銷毀沒啥關系了

(2)為什么inline聲明和定義分離到兩個文件會產生鏈接錯誤,鏈接是什么,為什么沒有函數地址:

??

inline之所以不建議聲明定義分離,是因為當我們假設在head.h頭文件里定義了內聯函數add(自定義函數名)然后分別在a.cpp里定義add函數然后在b.cpp里調用add函數然后運行,那么在對程序進行編譯時,會發現對于add函數頭文件里只有聲明而沒有定義,因此編譯器會假設add為一個外部函數(這里類似于一般函數的跨文件調用),但與一般函數調用不同的是,一般函數在假設外部函數時會同時在符號表生成一個對函數的引用(包含了未解析的地址),然后再在鏈接過程中通過對各文件的鏈接重新補全符號表里未解析的地址,從而實現函數聲明定義的分開,但inline函數卻不一樣,它同樣會在符號表里生成一個未解析的地址,但由于inline函數的性質就是對函數體代碼的整體替換從而實現對指令代碼的節約使用而且需要明確的內聯點才可以進行替換,因此這樣導致了其無法在鏈接時找到對應的內聯點進而不能像一般函數那樣在鏈接過程中補全對應的符號表里未解析的地址(內聯需要替換的代碼都找不到更別說地址了),從而發生鏈接的報錯

二.類,實例化和this指針

1.類的介紹(class):

其中有兩點需要特別注意

(a)?類中的成員函數默認為內聯

(b)關于訪問限定符:

如下代碼:public和private是訪問限定符,在public后面的成員函數和成員變量可以直接在類的外部使用,private后面的成員函數和成員變量不能被直接使用。 ? ? ??

? ? ? ? 通常我們把成員函數定義為public,把成員變量定義為private

#include<iostream>
using namespace std;
class TEST
{
public://成員函數void test(){return;}
private://成員變量int _a;int _b;
};
//以上class為類的關鍵字,TEST為類的名字,{}中的為類的主體//但同樣的,C++由于相當于C的pro max版,同時也可以兼容C中的struct結構:
typedef struct ListNodeC
{struct ListNodeC* next;int val;
}LTNode;int main()
{return 0;
}

關于類域

#include<iostream>
using namespace std;class TEST
{
public://成員函數聲明int test(int a, int b);private://成員變量int _a;int _b;
};
//類定義了一個新的作用域,類的所有成員函數都在類的作用域中。在類體外定義成員時,需要使用類域名::來訪問成員
//如果不指定類域的話,在定義函數時,程序在全局域找不到函數的聲明就會報錯。編譯器不會主動去類域中尋找函數定義
int TEST::test(int a, int b)
{return a + b;
}
int main()
{TEST A;int c = 10; int d = 20;cout << A.test(c, d) << endl;return 0;
}

2.實例化:

(1)實例化的概念:

(2)實例化的空間分配:

?對象的大小只包含成員變量的大小,成員函數不占內存空間

打個比方,現在實例化出了兩個類,分別為A,B但A和B的成員變量和地址是不同的,但如果訪問這兩個類的成員函數,他們都會鏈接到一個地址(只讀存儲區,靜態存儲),所以說我們sizeof(類對象)只用統計成員變量占用的空間

?成員變量占用的空間也符合內存對齊規則:

關于這個對齊其實有點比較容易遺忘,因此我再簡述一下:

1. 基本概念
?對齊:數據類型的起始地址必須是該類型大小的整數倍
?例如:?int?(4字節)的地址必須是 ?0x4, 0x8, 0xC...?
?未對齊:數據起始地址不滿足對齊規則,可能導致性能下降或硬件錯誤(如 ARM 架構)

2. 內存對齊規則
?a. 自然對齊
?規則:每個數據類型的地址必須是其自身大小的整數倍
?示例:

struct AlignedStruct {char a;        // 1字節 → 地址 0x0int b;        // 4字節 → 地址 0x4(填充3字節)double c;     // 8字節 → 地址 0x8(填充7字節)
};

b. 結構體對齊
成員順序:成員按聲明順序排列,每個成員按自然對齊對齊

舉例:

?
struct CompactStruct {int a;       // 0x0char b;      // 0x4(填充3字節)short c;     // 0x8
}; // 總大小:12字節(而非 16字節)?

3.this指針:

? Date類中有Init與Print兩個成員函數,函數體中沒有關于不同對象的區分,那當d1調?Init和 Print函數時,該函數是如何知道應該訪問的是d1對象還是d2對象呢?那么這?就要看到C++給了 ?個隱含的this指針解決這?的問題

? 編譯器編譯后,類的成員函數默認都會在形參第?個位置,增加?個當前類類型的指針,叫做this 指針。?如Date類的Init的真實原型為, void Init(Date* const this, int year, int month, int day)

? 類的成員函數中訪問成員變量,本質都是通過this指針訪問的,如Init函數中給_year賦值, this- >_year = year;

? C++規定不能在實參和形參的位置顯示的寫this指針(編譯時編譯器會處理),但是可以在函數體內顯示使?this指針

?另外需要注意一點,this指針其實存放在棧區,而不是對象里面

#include<iostream>
using namespace std;
class Date
{
public:// void Init(Date* const this, int year, int month, int day)void Init(int year, int month, int day){// this->_year = year;_year = year;this->_month = month;this->_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}
private:// 這?只是聲明,沒有開空間 int _year;int _month;int _day;
};int main()
{Date A;return 0;
}//成員函數在傳參時都有一個類的指針類型的this指針,這個this指針編譯器不會顯示出來,但實際上他是存在的,看上邊這串代碼,如果再函數調用賦值的時候,可以手動把this指針加上去,這樣其實并不會報錯。這就說明這個this指針是真實存在的

4.關于空指針訪問成員變量的注意點:

先看一下下面這兩個代碼:

? ? ? ?這兩串代碼運行的結果并不相同,已知第一個是正常運行,第二個是運行崩潰,首先我們應該知道不管是C語言中還是C++中,解引用空指針并不會編譯報錯,只會運行崩潰

其次再來分析問什么第二個是運行崩潰

? ? ? ? 首先成員函數不會占用物理內存,只有成員變量會,實例出nullptr說明沒開空間,但仔細看第一個程序是不需要訪問成員變量的,所以不開空間也沒有報錯,而第二個程序訪問了開空間的成員變量:_a,所以運行崩潰了

三.類的默認成員函數

默認成員函數就是??沒有顯式實現,編譯器會?動?成的成員函數稱為默認成員函數:

接下來我會對其中的幾個做出詳細介紹:

1.構造函數:

? ? ???構造函數也是一種成員函數但他和我們寫的普通構造函數不同的是,他是在我們實例化類的對象是默認調用的,也就是說,實例化對象是他自己會去主動調用這個構造函數,其本質是要替代我們以前Stack和Date類中寫的Init函數的功能,構造函數?動調?的 特點就完美的替代的了Init

接下來說說它的基本特點

函數名和類名相同;

沒有返回值:

#include<iostream>
using namespace std;
class DATE
{
public:DATE(int year = 2000, int mouth = 11, int day = 1){_year = year;_mouth = mouth;_day = day;}
private://成員函數//private成員函數不能直接訪問,可以通過成員函數訪問int _year;int _mouth;int _day;
};
int main()
{DATE d1;return 0;
}//上面這串代碼中定義了一個日期類,并實例化出一個對象d1,調試可以看到,實例化d1自動調用了DATE這個構造函數,給d1的三個成員變量進行了賦值//構造函數也有很多種,第一種無參構造函數。第二種是全缺省構造函數,第三種就是不寫構造時編譯器默認的構造函數(接下來我會具體說說這三種函數),如果我們在實例化的時候只寫這個對象就像上面這串代碼這樣:DATE d1; 這樣調用的構造函數叫默認構造

? ? ? ?

//無參構造函數
DATE()
{_year = 1;_mouth = 1;_day = 1;
}//全缺省構造函數
DATE(int year = 2000, int mouth = 11, int day = 1)
{_year = year;_mouth = mouth;_day = day;
}// 帶參構造函數 
Date(int year, int month, int day)
{_year = year;_month = month;_day = day;
}

? ? ? ?除了以上幾點還有一點需要額外注意:如果類中沒有顯式定義構造函數,則C++編譯器會?動?成?個?參的默認構造函數,?旦用戶顯式定義編譯器將不再?成,也就是說我們不寫,編譯器默認?成的構造,對內置類型成員變量的初始化沒有要求,也就是說是是否初始化是不確定的,看編譯器。對于?定義類型成員變量,要求調?這個成員變量的默認構造函數初始化,? 如果這個成員變量,沒有默認構造函數,那么就會報錯,我們要初始化這個成員變量,需要?初始化列表才能解決,初始化列表的問題,本文先放一下,下一篇文章再作詳細介紹

? ? ? ?讀到這里,會發現一個問題就是既然系統會自動生成默認構造函數,那為什么我們還需要自己去寫構造函數?舉個例子:

當類需要動態分配內存(如 new ?或 malloc )時,默認構造函數無法自動釋放資源,必須手動管理:

class Buffer {
public:int* data; // 動態內存// 自定義構造函數:初始化 dataBuffer(int size) : data(new int[size]) {std::cout << "Buffer initialized with size " << size << std::endl;}// 析構函數:釋放資源~Buffer() {delete[] data;std::cout << "Buffer destroyed" << std::endl;}
};int main() {Buffer buf(1024); // 調用自定義構造函數return 0;
}

默認構造函數不會初始化 data ,導致未定義行為(如懸空指針),自定義構造函數確保 data 正確分配內存

2.析構函數:

? ? ? ?析構函數可以在類對象銷毀時自動調用,釋放我們的內存空間。就好比之前實現的棧這個數據結構,我們需要把我們malloc出來的空間都free掉,那么這個時候如果是使用c++里面的類來完成的話,在我們的棧銷毀時(該對象生命周期結束時)就可以自動調用析構函數釋放內存


~Stack()
{cout << "~Stack()" << endl;free(_a);_a = nullptr;_top = _capacity = 0;
}

析構的特點也很明顯:

1.?析構函數名是在類名前加上字符~

2.不需要寫返回值

3.和構造函數一樣,我們不寫編譯器?動?成的析構函數對內置類型成員不做處理,?定類型成員會調?他的析構函數

4.一個類只有一個析構且當類成員不需要釋放空間時,不需要自己寫析構函數

#include<iostream>
using namespace std;
typedef int STDataType;
class Stack
{
public:Stack(int n = 4){_a = (STDataType*)malloc(sizeof(STDataType) * n);if (nullptr == _a){perror("malloc申請空間失敗");return;}_capacity = n;_top = 0;}~Stack(){cout << "~Stack()" << endl;free(_a);_a = nullptr;_top = _capacity = 0;}
private:STDataType* _a;size_t _capacity;size_t _top;
};

3.拷貝構造函數:

如果?個構造函數的第?個參數是??類類型的引?,且任何額外的參數都有默認值,則此構造函數 也叫做拷貝構造函數,也就是說拷貝構造是?個特殊的構造函數

#include<iostream>
using namespace std;class DATE
{
public:DATE(int year, int mouth, int day){_year = year;_mouth = mouth;_day = day;}void Print(){cout << _year << "年" << _mouth << "月" << _day << "日" << endl;}
private://成員函數//private成員函數不能直接訪問,可以通過成員函數訪問int _year;int _mouth;int _day;
};
int main()
{DATE d1(10,10,10);DATE d2(d1);//調用拷貝構造d1.Print();d2.Print();return 0;
}
//注意,第一個參數必須是引用。否則編譯器會報錯。為什么會報錯呢?理解一下,如果說我們傳入的第一個參數沒有引用,那么這個形參是得拷貝一份我們的實參,怎么拷貝呢?他還是得調用我們的拷貝構造函數去拷貝,那這就形成了閉環,而這樣無限拷貝下去編譯器是不允許的//對于沒有主動寫拷貝構造的類,編譯器也會默認生成一個拷貝構造,對于內置類型進行淺拷貝,也就是只拷貝值,對于自定義類型成員會調用他的拷貝構造。

但還有幾點需要注意:

1.像Date這樣的類成員變量全是內置類型且沒有指向什么資源,編譯器?動?成的拷?構造就可以完 成需要的拷?,所以不需要我們顯?實現拷?構造,但像Stack這樣的類,雖然也都是內置類型,但 是_a指向了資源,編譯器?動?成的拷?構造完成的值拷?/淺拷?不符合我們的需求,所以需要我們??實現深拷?(對指向的資源也進?拷?),像MyQueue這樣的類型內部主要是?定義類型 Stack成員,編譯器?動?成的拷?構造會調?Stack的拷?構造,也不需要我們顯?實現 MyQueue的拷?構造(前提是Stack這個類有析構)

2.傳值返回會產??個臨時對象調?拷?構造傳值引?返回,返回的是返回對象的別名(引?),沒有產?拷?。但是如果返回對象是?個當前函數局部域的局部對象,函數結束就銷毀了,那么使? 引?返回是有問題的,這時的引?相當于?個野引?,類似?個野指針?樣。傳引?返回可以減少拷?,但是?定要確保返回對象在當前函數結束后還在,才能?引?返回

4.運算符重載:

運算符重載簡而言之就是賦予我們常見的運算符以新的定義與使用場景,比如+號原來只可以用于數字之間的運算,但經過運算符重載之后,使其可以進行日期之間的計算,諸如此類:

bool operator==(DATE x)
{return _year == x._year && _mouth == x._mouth && _day == x._day;
}

以下是幾個注意點:

1.不能對c++沒有的符號進行重載

2、以下五個運算符不能進行重載:

.* ? ? ?:: ? ? ?sizeof ? ? ? ? : ? ? ? .

3.運算符重載的參數列表至少要含有一個自定義類型,不能通過運算符重載改變內置類型對象的含義,如: int operator+(int x, int y)

4.重載++運算符時,有前置++和后置++,運算符重載函數名都是operator++,無法很好的區分。 C++規定,后置++重載時,增加?個int形參,跟前置++構成函數重載,方便區分

四.日期類實現

//Date.h
#pragma once
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
class DATE
{
public:DATE(int year = 2000, int mouth = 11, int day = 1){_year = year;_mouth = mouth;_day = day;}//短小多次調用函數使用inline//clase默認inlineint GetMouthDay(int year, int mouth){assert(mouth > 0 && mouth < 13);static int mouthDayArray[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };//多次訪問直接定義靜態數組if (mouth == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))//讓容易不通過的條件放前面{return 29;}else return mouthDayArray[mouth];}DATE& operator+=(int day);//聲明運算符重載DATE& operator+(int day);void Print(){cout << _year << "年" << _mouth << "月" << _day << "日" << endl;}//日期比較bool operator>(DATE x){if (_year > x._year) return true;else if (_year < x._year) return false;if (_mouth > x._mouth) return true;else if (_mouth < x._mouth) return false;if (_day > x._day) return true;else return false;}bool operator==(DATE x){return _year == x._year && _mouth == x._mouth && _day == x._day;}bool operator < (DATE x){return !(*this > x) && !(*this == x);}bool operator!=(DATE& d2){return !(*this == d2);}DATE operator++(int){//后置加加返回原值//注意這個臨時變量出了這個函數就銷毀了所以不能引用返回DATE tmp(*this);_day++;if (_day > GetMouthDay(_year, _mouth)){_day = 1; _mouth++;}if (_mouth > 12){_year++;_mouth = 1;}return tmp;}//兩日期相減int operator-(DATE& d1);
private://成員函數//private成員函數不能直接訪問,可以通過成員函數訪問int _year;int _mouth;int _day;
};
//text.cpp#include"DATE.h"DATE& DATE::operator+=(int day)//表明所屬類
{//由于更改了自身所以重載的是+=//引用返回可以避免拷貝,節省開銷//不能返回空值,不然無法解決這種問題(a+=10)+=10//對于這種情況如果傳dATE返回的話也無法改變原值,不符合預期。_day += day;while (_day > GetMouthDay(_year, _mouth)){_day -= GetMouthDay(_year, _mouth);++_mouth;if (_mouth == 13){_year++;_mouth = 1;}}return *this;
}
DATE& DATE::operator+(int day)
{//DATE tmp(*this);//拷貝//默認構造函數DATE tmp = *this;///同樣也是調用默認構造函數tmp += day;return tmp;
}
int DATE::operator-(DATE& d1)
{int cnt = 0;int flag = 1;DATE max = *this;DATE min = d1;if (max < min){flag = -1;max = d1;min = *this;}while (max != min){cnt++;min++;}return cnt * flag;
}

以上就是關于日期類相關的函數代碼了

歐克,時間也不晚了,就到這里吧

全文終

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

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

相關文章

C++中,存儲持續性、作用域和鏈接性

在C++中,存儲持續性、作用域和鏈接性是變量和函數的重要屬性,它們共同決定了變量的生命周期、可見性以及跨文件訪問能力。以下是詳細的總結: 1. 存儲持續性(Storage Duration) 存儲持續性指變量在內存中的生命周期,分為四類: 自動存儲持續性(Automatic) 局部變量(函…

四種 No-SQL

在一個常規的互聯網服務中&#xff0c;讀取與寫入的比例大約是 100:1 到 1000:1。然而&#xff0c;從硬盤讀取時&#xff0c;數據庫連接操作耗時&#xff0c;99% 的時間花費在磁盤尋址上。 為了優化讀取性能&#xff0c;非規范化的設計通過添加冗余數據或分組數據來引入。下述…

【 Manus平替開源項目】

文章目錄 Manus平替開源項目1 OpenManus1.1 簡介1.2 安裝教程1.3 運行 2 OWL2.1 簡介2.2 安裝教程2.3 運行 3 OpenHands&#xff08;原OpenDevin&#xff09;3.1 簡介3.2 安裝教程和運行 Manus平替開源項目 1 OpenManus 1.1 簡介 開發團隊: MetaGPT 核心貢獻者&#xff08;5…

【Linux 服務之ollama 部署過慢問題】

特別慢的 curl -fsSL https://ollama.com/install.sh | sh參考 方法1 export OLLAMA_MIRROR"https://ghproxy.cn/https://github.com/ollama/ollama/releases/latest/download" curl -fsSL https://ollama.com/install.sh | sed "s|https://ollama.com/downl…

療養院管理系統設計與實現(代碼+數據庫+LW)

摘 要 傳統辦法管理信息首先需要花費的時間比較多&#xff0c;其次數據出錯率比較高&#xff0c;而且對錯誤的數據進行更改也比較困難&#xff0c;最后&#xff0c;檢索數據費事費力。因此&#xff0c;在計算機上安裝療養院管理系統軟件來發揮其高效地信息處理的作用&#xf…

Web后端開發之Maven

Maven Mven是apache旗下的一個開源項目&#xff0c;用來管理和構建java項目的工具。 通過一小段描述信息來管理項目。 Maven的作用 1.依賴管理&#xff1a;方便快捷的管理項目依賴的資源&#xff08;jar包&#xff09;&#xff0c;避免版本沖突問題 以前用某個jar包需要下載…

在線招聘小程序:AI簡歷篩選與精準職位推薦服務

當AI算法遇上小程序開發:重新定義「人崗匹配」的智能招聘革命 一、傳統招聘困境:求職者與企業為何總在「錯過」? 在數字化浪潮下,企業HR日均需處理數百份簡歷,卻仍有60%的崗位因匹配效率低下而空置;求職者海投簡歷后,近八成用戶表示從未收到精準反饋。這種雙向資源錯配…

Linux文件IO——緩沖區磁盤上的文件管理

前言 什么是緩沖區&#xff1f; 緩沖區是內存空間上的一小段內存&#xff0c;我們平常在寫程序的時候&#xff0c;其實是很難感知到緩沖區的存在的&#xff0c;接下來看一段代碼&#xff0c;可以很好地體現緩沖區的存在。 #include<stdio.h> #include<unistd.h> in…

Java中如何去自定義一個類加載器

之前寫過一篇&#xff0c;關于 類加載器和雙親委派的文章&#xff0c;里邊提到過可以根據自己的需要&#xff0c;去寫一個自定義的類加載器&#xff0c;正好有人問這個問題&#xff0c;今天有時間就來手寫一個自定義的類加載器&#xff0c;并使用這個自定義的類加載器來加載一個…

X86 RouterOS 7.18 設置筆記六:端口映射(IPv4、IPv6)及回流問題

X86 j4125 4網口小主機折騰筆記五&#xff1a;PVE安裝ROS RouterOS X86 RouterOS 7.18 設置筆記一&#xff1a;基礎設置 X86 RouterOS 7.18 設置筆記二&#xff1a;網絡基礎設置(IPV4) X86 RouterOS 7.18 設置筆記三&#xff1a;防火墻設置(IPV4) X86 RouterOS 7.18 設置筆記四…

代碼隨想錄|二叉樹|21合并二叉樹

leetcode:617. 合并二叉樹 - 力扣&#xff08;LeetCode&#xff09; 題目 給定兩個二叉樹&#xff0c;想象當你將它們中的一個覆蓋到另一個上時&#xff0c;兩個二叉樹的一些節點便會重疊。 你需要將他們合并為一個新的二叉樹。合并的規則是如果兩個節點重疊&#xff0c;那么…

LDR6500在Type-C轉DP視頻雙向互傳方案

LDR6500在Type-C轉DP視頻雙向互傳方案中扮演著核心角色&#xff0c;以下是對該方案的詳細解析&#xff1a; 一、LDR6500芯片概述 LDR6500是樂得瑞科技針對USB Type-C標準中的Bridge設備而開發的USB-C DRP&#xff08;Dual Role Port&#xff0c;雙角色端口&#xff09;接口USB…

Vue3中 ref 與 reactive區別

ref 用途: ref 通常用于創建一個響應式的基本類型數據&#xff08;如 string、number、boolean 等&#xff09;&#xff0c;但它也可以用于對象或數組 返回值: ref 返回一個帶有 .value 屬性的對象&#xff0c;訪問或修改數據需要通過 .value 進行 使用場景: …

CRM企業客戶關系管理系統產品原型方案

客戶關系管理系統&#xff08;CRM&#xff09;是企業產品應用中的典范&#xff0c;旨在通過信息技術和互聯網技術提升企業核心競爭力&#xff0c;優化企業與顧客在銷售、營銷和服務方面的互動。本作品提供了一套通用型的CRM系統原型模板&#xff0c;涵蓋數據管理、審批流程、統…

【算法】 【c++】字符串s1 中刪除所有 s2 中出現的字符

【算法】 【c】字符串s1 中刪除所有 s2 中出現的字符 eg&#xff1a; s1:“helloworld” s2:“wd” 刪除后&#xff1a;s1:“helloorl” 1 雙循環匹配并刪除–>時間復雜度O(n^2) string 里面的刪除函數–>erase std::string::erase 是 C 標準庫中用于刪除字符串中字符…

利用委托用戶控件、窗體之間傳值 c#

獲取數據方&#xff08;usercontrol111&#xff09;聲明 public Func<Tuple<int, int>> GetCurrentResult { get; set; }獲取數據方調用 var val GetCurrentResult?.Invoke() ?? new Tuple<decimal, decimal>(0, 0);數據發送方聲明與賦值 usercontrol111…

【3-14 STC-pair超級詳細的解說】

1. pair的定義和結構 ? 基礎概念&#xff1a;考察對std::pair模板類的理解&#xff0c;包括其頭文件&#xff08;<utility>&#xff09;和基本語法&#xff08;pair<T1, T2>&#xff09;。 ? 成員訪問&#xff1a;測試對first和second成員變量的使用能力。 ? 構…

機器人觸覺的意義

機器人觸覺的重要性 觸覺在機器人領域至關重要&#xff0c;尤其是在自主操作、精細操控、人機交互等方面。雖然視覺和語音技術已高度發展&#xff0c;但機器人在現實世界中的操作仍然受限&#xff0c;因為&#xff1a; 視覺有局限性&#xff1a;僅憑視覺&#xff0c;機器人難…

RabbitMQ消息持久化與Lazy模式對比分析

RabbitMQ消息持久化與Lazy模式對比分析 在RabbitMQ中&#xff0c;消息持久化與Lazy模式是兩種不同的機制&#xff0c;分別針對消息可靠性、存儲優化等不同維度設計。以下從六個層面進行深度對比&#xff1a; 一、核心目標與作用對象差異 維度消息持久化&#xff08;delivery_…

Search-R1 、 R1-Searcher 和 Search-O1

原文鏈接:https://i68.ltd/notes/posts/20250307-search-r1/ Search-R1 DeepSeek團隊開發的SEARCH-R1模型通過強化學習&#xff0c;讓AI學會了自主搜索信息并將其與推理過程無縫結合&#xff0c;性能提升高達26%高效、可擴展的RL訓練框架&#xff0c;用于推理和搜索引擎調用&…