C++編程之旅-- -- --默認成員函數(全詳解)

目錄

  • 前言
  • 構造函數
    • 構造函數形式:
    • 構造函數的特性:
    • explicit關鍵字
  • 析構函數
    • 析構函數的概念
    • 析構函數的特性
    • 含有類類型的成員變量的類析構函數的調用
  • 拷貝構造函數
    • 拷貝構造函數的概念
    • 拷貝構造函數的特性
    • 淺拷貝和深拷貝:
    • 拷貝構造函數典型調用場景:
  • 賦值運算符重載
    • 運算符重載
    • 全局的operator==
    • 賦值運算符重載
    • 前置++和后置++重載
  • const成員函數
  • 取地址及const取地址操作符重載#

前言

如果一個類是沒什么也沒有,就叫做空類。

空類并非什么也沒有,它占一個字節。編譯器會自動生成6個默認成員函數。

默認成員函數:指沒有顯式實現(自己寫),編譯器生成的成員函數

在這里插入圖片描述

構造函數

Data類:

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;d1.Init(2022, 7, 5);d1.Print();Date d2;d2.Init(2022, 7, 6);d2.Print();return 0;
}

創建類對象時,每次都要把數據通過Init成員函數設置(麻煩)。構造函數就是在創建類對象時就能將數據設置(解決麻煩)。

構造函數形式:

 class Date{public:// 1.無參構造函數Date(){}// 2.帶參構造函數Date(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;};void TestDate(){Date d1; // 調用無參構造函數Date d2(2015, 1, 1); // 調用帶參的構造函數// 注意:如果通過無參構造函數創建對象時,對象后面不用跟括號,否則就成了函數聲明// 以下代碼的函數:聲明了d3函數,該函數無參,返回一個日期類型的對象// warning C4930: “Date d3(void)”: 未調用原型函數(是否是有意用變量定義的?)Date d3();}

構造函數的特性:

  1. 函數名與類名相同。
  2. 無返回值。
  3. 對象實例化時編譯器自動調用對應的構造函數。
  4. 構造函數可以重載。

優先級:顯式實現構造函數>>默認構造函數。

使用默認函數,它對成員變量(基本類型)的賦值時隨機值:
在這里插入圖片描述
C++把類型分成內置類型(基本類型)和自定義類型內置類型就是語言提供的數據類型,如:int/char…自定義類型就是我們使用class/struct/union等自己定義的類型。

對于類類型成員, 編譯器生成默認的構造函數會對自定類型成員_t調用的它的默認成員函數

C++11 中針對內置類型成員不初始化的缺陷,又打了補丁,即:內置類型成員變量在 類中聲明時可以給默認值。):解決使用默認函數,看上去沒有什么用,它對成員變量(基本類型)的賦值時隨機值

class Time
{
public:Time(){cout << "Time()" << endl;_hour = 0;_minute = 0;_second = 0;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本類型(內置類型)int _year=1970;int _month=12;int _day=29;// 自定義類型Time _t;
};

運行結果:
在這里插入圖片描述

無參的構造函數和全缺省的構造函數都稱為默認構造函數,并且默認構造函數只能有一個

class Date
{
public:Date(){_year = 1900;_month = 1;_day = 1;}Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
void Test()
{Date d1;
}

運行結果:
在這里插入圖片描述

構造函數是為了初始化,然而初始化只有一次,用構造函數卻能多次,這違背了初始化的初衷。
因此在構造函數里初始化列表,便解決了這一問題。

之前的構造函數都是構造函數體賦值。構造函數體中的語句只能將其稱為賦初值,而不能稱作初始化

class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};

初始化列表:一個冒號,再寫成員變量,成員變量后面加(),()里是初始值或表達式。

class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}private:int _year;int _month;int _day;
};

注意

  1. 每個成員變量在初始化列表中只能出現一次(初始化只能初始化一次)。
  2. 成員變量在類中聲明次序就是其在初始化列表中的初始化順序,與其在初始化列表中的先后次序無關。
  3. 類中包含以下成員,必須放在初始化列表位置進行初始化

引用成員變量
const成員變量
自定義類型成員(且該類沒有默認構造函數時)

class A
{
public:A(int a):_a(a){}
private:int _a;
};
class B
{
public:B(int a, int ref):_aobj(a),_ref(ref),_n(10){}
private:A _aobj; // 沒有默認構造函數int& _ref; // 引用const int _n; // const 
};

否則:
在這里插入圖片描述

explicit關鍵字

構造函數不僅可以構造與初始化對象,對于接收單個參數的構造函數,還具有類型轉換的作用。 而explicit關鍵字就是限制隱式類型轉換。

接收單個參數的構造函數具體表現

  1. 構造函數只有一個參數。
  2. 構造函數有多個參數,除第一個參數沒有默認值外,其余參數都有默認值。
  3. 全缺省構造函數。
class Date
{
public:// 1. 單參構造函數,沒有使用explicit修飾,具有類型轉換作用// explicit修飾構造函數,禁止類型轉換---explicit去掉之后,代碼可以通過編譯explicit Date(int year):_year(year){}// 2. 雖然有多個參數,但是創建對象時后兩個參數可以不傳遞,沒有使用explicit修飾,具有類型轉換作用// explicit修飾構造函數,禁止類型轉換explicit Date(int year, int month = 1, int day = 1): _year(year), _month(month), _day(day){}private:int _year;int _month;int _day;
};
void Test()
{Date d1(2022);	// 用一個整形變量給日期類型對象賦值d1 = 2023;		// 實際編譯器背后會用2023構造一個無名對象,最后用無名對象給d1對象進行賦值。}

C++ 里,單個參數的構造函數(或參數帶默認值、能簡化成單個參數的構造函數 ),會讓編譯器允許 用單個值直接給對象賦值,這叫隱式類型轉換如果用了explicit,那么就不能用單個值直接給對象賦值。

析構函數

析構函數的概念

析構函數與構造函數功能相反。析構函數不是完成對對象本身的銷毀,局部對象銷毀工作是由編譯器完成的。而對象在銷毀時會自動調用析構函數,完成對象中資源的清理工作。簡單來說就是把對象里占的額外資源(文件、動態內存)清理掉,避免殘留、浪費。

析構函數的特性

  1. 析構函數名是在類名前加上字符 ~。
  2. 無參數無返回值類型
  3. 一個類只能有一個析構函數。若未顯式定義,系統會自動生成默認的析構函數。注意:析構
    函數不能重載。
  4. 對象生命周期結束時,C++編譯系統系統自動調用析構函數。
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申請空間失敗!!!");return;}_capacity = capacity;_size = 0;}void Push(DataType data){// CheckCapacity();_array[_size] = data;_size++;}// 其他方法...~Stack(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}}
private:DataType* _array;int _capacity;int _size;
};
void TestStack()
{Stack s;s.Push(1);s.Push(2);
}

含有類類型的成員變量的類析構函數的調用

class Time
{
public:~Time(){cout << "~Time()" << endl;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本類型(內置類型)int _year = 1970;int _month = 1;int _day = 1;// 自定義類型Time _t;
};
int main()
{Date d;return 0;
}
// 程序運行結束后輸出:~Time()
// 在main方法中根本沒有直接創建Time類的對象,為什么最后會調用Time類的析構函數?
// 因為:main方法中創建了Date對象d,而d中包含4個成員變量,其中_year, _month, _day三個是
// 內置類型成員,銷毀時不需要資源清理,最后系統直接將其內存回收即可;而_t是Time類對象,所以在
// d銷毀時,要將其內部包含的Time類的_t對象銷毀,所以要調用Time類的析構函數。但是:main函數
// 中不能直接調用Time類的析構函數,實際要釋放的是Date類對象,所以編譯器會調用Date類的析構函
// 數,而Date沒有顯式提供,則編譯器會給Date類生成一個默認的析構函數,目的是在其內部調用Time
// 類的析構函數,即當Date對象銷毀時,要保證其內部每個自定義對象都可以正確銷毀
// main函數中并沒有直接調用Time類析構函數,而是顯式調用編譯器為Date類生成的默認析構函數
// 注意:創建哪個類的對象則調用該類的析構函數,銷毀那個類的對象則調用該類的析構函數

運行結果:
在這里插入圖片描述

簡單來說:mian函數中無法調用Time里面的析構函數,但想將d銷毀就要把_t給銷毀,這是編譯器就會自動生成析構函數來去調用Time里面的析構函數將_t銷毀(內置類型系統會直接將其內存回收)

注意:有資源申請時,一定要寫析構函數,否則會造成資源泄漏

拷貝構造函數

拷貝構造函數的概念

拷貝構造函數,就是以一個類對象來創建一個一摸一樣的類對象

拷貝構造函數:只有單個形參,該形參是對本類類型對象的引用(一般常用const修飾),在用已存
在的類類型對象創建新對象時由編譯器自動調用。


拷貝構造函數的特性

拷貝構造函數是構造函數的一個重載形式

拷貝構造函數的參數只有一個且必須是類類型對象的引用,使用傳值方式編譯器直接報錯,
因為會引發無窮遞歸調用

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// Date(const Date d)   // 錯誤寫法:編譯報錯,會引發無窮遞歸Date(const Date& d)   // 正確寫法{_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;Date d2(d1);return 0;
}

在這里插入圖片描述

若未顯式定義,編譯器會生成默認的拷貝構造函數。 默認的拷貝構造函數對象按內存存儲 按
字節序完成拷貝,這種拷貝叫做淺拷貝,或者值拷貝。

class Time
{
public:Time(){_hour = 1;_minute = 1;_second = 1;}Time(const Time& t){_hour = t._hour;_minute = t._minute;_second = t._second;cout << "Time::Time(const Time&)" << endl;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本類型(內置類型)int _year = 1970;int _month = 1;int _day = 1;// 自定義類型Time _t;
};
int main()
{Date d1;// 用已經存在的d1拷貝構造d2,此處會調用Date類的拷貝構造函數// 但Date類并沒有顯式定義拷貝構造函數,則編譯器會給Date類生成一個默認的拷貝構造函數Date d2(d1);return 0;
}

淺拷貝和深拷貝:

淺拷貝是默認的拷貝方式:編譯器自動生成的拷貝構造函數會按 字節序 逐成員復制,對于指針成員,只復制指針的地址值,而不復制指針指向的底層數據。

typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申請空間失敗");return;}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType *_array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
}

類里面沒有拷貝構造函數,那么編譯器會生成默認構造構造函數,而它是以按 字節序 逐成員復制,但類成員變量里面有指針,拷貝構造函數只會賦值地址值。而當拷貝一個新的類對象時,s1與s2里的array會指向同一塊空間,這時析構會重復釋放兩次通空間。因此有動態資源,就需要深拷貝。


深拷貝是手動實現的拷貝方式:不僅復制對象的成員變量,還會為指針等動態資源重新分配內存,并復制底層數據,讓新對象和原對象擁有完全獨立的資源。

typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申請空間失敗");return;}_size = 0;_capacity = capacity;}Stack(const  DataType& other){_array = (DataType*)malloc(other._capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申請空間失敗");return;}// 2. 復制原對象的元素(深拷貝核心:不僅復制指針,還要復制數據)memcpy(_array, other._array, other._size * sizeof(DataType));// 3. 復制大小和容量_size = other._size;_capacity = other._capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType *_array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
}

簡單來說就是自己手寫完成不是地址值,而是數據的傳遞。
在這里插入圖片描述

只要類中包含需要手動管理的動態資源,就必須實現深拷貝:

指針指向堆內存(new/delete 分配的資源)。
包含文件句柄、網絡連接等“獨占性資源”。
成員變量是其他帶動態資源的類類型(需確保成員類自身也實現了深拷貝)

拷貝構造函數典型調用場景:

使用已存在對象創建新對象
函數參數類型為類類型對象
函數返回值類型為類類型對象

class Date
{
public:Date(int year, int minute, int day){cout << "Date(int,int,int):" << this << endl;}Date(const Date& d){cout << "Date(const Date& d):" << this << endl;}~Date(){cout << "~Date():" << this << endl;}
private:int _year;int _month;int _day;
};
Date Test(Date d)
{Date temp(d);return temp;
}
int main()
{Date d1(2022,1,13);Test(d1);return 0;
}

在這里插入圖片描述

為了提高程序效率,一般對象傳參時,盡量使用引用類型,返回時根據實際場景,能用引用
盡量使用引用

賦值運算符重載

運算符重載

C++為了增強代碼的可讀性引入了運算符重載,運算符重載是具有特殊函數名的函數

函數原型:返回值類型 operator操作符(參數列表)

注意事項:

不能通過連接其他符號創建新的操作符(不可行):比如operator@。 重載操作符必須有一個類類型參數
用于內置類型的運算符,其含義不能改變,例如:內置的整型+,不 能改變其含義。
作為類成員函數重載時,其形參看起來比操作數數目少1,因為
成員函數的第一個參數為隱

藏的this
. :: sizeof ?: . 注意以上5個運算符不能重載。(牢記牢記牢記)*

全局的operator==

class Date
{ 
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}    
//private:int _year;int _month;int _day;
};
bool operator==(const Date& d1, const Date& d2)
{return d1._year == d2._year&& d1._month == d2._month&& d1._day == d2._day;
}
void Test ()
{Date d1(2018, 9, 26);Date d2(2018, 9, 27);cout<<(d1 == d2)<<endl;
}

要使operator==成為全局的,就要將成員變量成公有。因為實在類外實現的,所以訪問類里面的東要公有。
但這就會出限一個問題:封裝性降低。如何解決呢?:友元和將 operator= =放入類里(這個好像與要求背道而馳了。)

operator= =放入類里參數有一個最左邊的this指針):

class Date
{ 
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// bool operator==(Date* this, const Date& d2)// 這里需要注意的是,左操作數是this,指向調用函數的對象bool operator==(const Date& d2){return _year == d2._year;&& _month == d2._month&& _day == d2._day;}
private:int _year;int _month;int _day;
};

賦值運算符重載

賦值運算符重載格式:

參數類型:const T&,傳遞引用可以提高傳參效率( T指類)
返回值類型:T&,返回引用可以提高返回的效率,有返回值目的是為了支持連續賦值
檢測是否自己給自己賦值
返回*this :要復合連續賦值的含義

class Date
{ 
public :Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date (const Date& d){_year = d._year;_month = d._month;_day = d._day;}Date& operator=(const Date& d){if(this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}
private:int _year ;int _month ;int _day ;
};

賦值運算符只能重載成類的成員函數不能重載成全局函數不能出類外):

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}int _year;int _month;int _day;
};
// 賦值運算符重載成全局函數,注意重載成全局函數時沒有this指針了,需要給兩個參數
Date& operator=(Date& left, const Date& right)
{if (&left != &right){left._year = right._year;left._month = right._month;left._day = right._day;}return left;
}

運行結果:
在這里插入圖片描述
原因:賦值運算符如果不顯式實現,編譯器會生成一個默認的。此時用戶再在類外自己實現
一個全局的賦值運算符重載,就和編譯器在類中生成的默認賦值運算符重載沖突了。

如果沒有顯式實現時,編譯器會生成一個默認賦值運算符重載,以值的方式逐字節拷貝那么也會有淺拷貝的類似問題。

typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申請空間失敗");return;}_size = 0;_capacity = capacity;}Stack(const  DataType& other){_array = (DataType*)malloc(other._capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申請空間失敗");return;}// 2. 復制原對象的元素(深拷貝核心:不僅復制指針,還要復制數據)memcpy(_array, other._array, other._size * sizeof(DataType));// 3. 復制大小和容量_size = other._size;_capacity = other._capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}Stack& operator=(const Stack& other){// 1. 檢查自賦值,避免自身賦值時的錯誤if (this != &other){// 2. 釋放當前對象的舊資源free(_array);// 3. 分配新內存_array = (DataType*)malloc(other._capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申請空間失敗");return *this;}// 4. 深拷貝數據memcpy(_array, other._array, other._size * sizeof(DataType));// 5. 復制其他成員變量_size = other._size;_capacity = other._capacity;}// 6. 返回當前對象引用,支持鏈式賦值return *this;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType *_array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2;s2 = s1;  // 現在可以安全地使用賦值運算符了Stack s3 = s1;  // 這調用的是拷貝構造函數,不是賦值運算符return 0;
}

賦值運算符重載(處理 “給已有對象賦值”)可以處理這個(s2 = s1;)。

前置++和后置++重載

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// 前置++:返回+1之后的結果// 注意:this指向的對象函數結束后不會銷毀,故以引用方式返回提高效率Date& operator++(){_day += 1;return *this;}// 后置++:// 前置++和后置++都是一元運算符,為了讓前置++與后置++形成能正確重載// C++規定:后置++重載時多增加一個int類型的參數,但調用函數時該參數不用傳遞,編譯器自動傳遞// 注意:后置++是先使用后+1,因此需要返回+1之前的舊值,故需在實現時需要先將this保存一份,然后給this+1// 而temp是臨時對象,因此只能以值的方式返回,不能返回引用Date operator++(int){Date temp(*this);_day += 1;return temp;}
private:int _year;int _month;int _day;
};
int main()
{Date d;Date d1(2022, 1, 13);d = d1++;    // d: 2022,1,13   d1:2022,1,14d = ++d1;    // d: 2022,1,15   d1:2022,1,15return 0;
}

在這里插入圖片描述

const成員函數

將const修飾的“成員函數”稱之為const成員函數,const修飾類成員函數,實際修飾該成員函數
隱含的this指針,表明在該成員函數中不能對類的任何成員進行修改。

在這里插入圖片描述

class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << "Print()" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}void Print() const{cout << "Print()const" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}
private:int _year; // 年int _month; // 月int _day; // 日
};
void Test()
{Date d1(2022,1,13);d1.Print();const Date d2(2022,1,13);d2.Print();
}

1.const 對象可以調用非 const 成員函數嗎?
不能。const對象調用成員函數時,編譯器會檢查函數是否為const,非const成員函數可能修改對象狀態,為保證const對象只讀”,禁止調用

2.非 const 對象可以調用 const 成員函數嗎?
可以。const成員函數承諾 “不修改對象”,非const對象調用時,不會破壞對象狀態,因此允許。

3.const 成員函數內可以調用其它的非 const 成員函數嗎?
不能。const成員函數中,this是const 類名*類型,調用非const成員函數會嘗試去掉const,可能破壞對象const性,編譯器禁止。

4.非 const 成員函數內可以調用其它的 const 成員函數嗎?
可以。非const成員函數中,this是類名*類型,調用const成員函數時,const成員函數的 “只讀”特性與非const對象兼容,允許調用。

取地址及const取地址操作符重載#

這兩個默認成員函數一般不用重新定義 ,編譯器默認會生成

class Date
{ 
public :Date* operator&(){return this ;}const Date* operator&()const{return this ;}
private :int _year ; // 年int _month ; // 月int _day ; // 日
};

可以在想讓別人獲取到指定的內容特殊情況時,才需要重載。

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

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

相關文章

Linux網絡編程:TCP的遠程多線程命令執行

目錄 前言&#xff1a; 一、前文補充 二、服務端的修改 三、Command類的新增 前言&#xff1a; 好久不見&#xff0c;最近忙于其他事情&#xff0c;就耽誤了咱們的Linux的網絡部分的學習。 今天咱們先來給之前所學的TCP的部分進行一個首尾工作&#xff0c;主要是給大家介紹…

重學React(三):狀態管理

背景&#xff1a; 繼續跟著官網的流程往后學&#xff0c;之前已經整理了描述UI以及添加交互兩個模塊&#xff0c;總體來說還是收獲不小的&#xff0c;至少我一個表面上用了四五年React的前端小卡拉米對React的使用都有了新的認知。接下來就到了狀態管理&#xff08;React特地加…

java web項目入門了解

目錄一、項目流程1. 使用servle2. 使用框架二、了解java web項目構造1. 項目目錄結構2. 查看頁面訪問順序3. 發起請求&#xff1a;jqueryajax4. 接受參數5. JSONJSON 數組三、get和post請求區別一、項目流程 1. 使用servle 有客戶端和服務端&#xff0c;客戶端和服務端進行交…

網絡資源模板--基于Android Studio 實現的日記本App

目錄 一、測試環境說明 二、項目簡介 三、項目演示 四、部設計詳情&#xff08;部分) 創建修改頁面 五、項目源碼 一、測試環境說明 電腦環境 Windows 11 編寫語言 JAVA 開發軟件 Android Studio (2020) 開發軟件只要大于等于測試版本即可(近幾年官網直接下載也可…

GO的啟動流程(GMP模型/內存)

目錄第一部分&#xff1a;程序編譯第二部分&#xff1a;函數解讀1&#xff09;Golang 核心初始化過程2&#xff09;創建第一個協程3&#xff09;啟動系統調度4&#xff09;跳轉main函數5&#xff09;總結第三部分&#xff1a;GMP模型Goroutine流程解讀第四部分&#xff1a;內存…

OLTP與OLAP:實時處理與深度分析的較量

OLTP&#xff08;Online Transaction Processing&#xff09;定義&#xff1a;OLTP 系統主要用于管理事務性應用程序的數據。這類系統需要支持大量的短時、快速的交互式事務&#xff0c;比如銀行交易、在線購物訂單等。特點&#xff1a;實時處理&#xff1a;OLTP 系統要求對數據…

數據安全與隱私保護:企業級防護策略與技術實現

引言&#xff1a;數據安全的新時代挑戰在數字化轉型加速的今天&#xff0c;數據已成為企業最核心的資產。然而&#xff0c;數據泄露事件頻發&#xff0c;據 IBM《2024 年數據泄露成本報告》顯示&#xff0c;全球數據泄露平均成本已達445 萬美元&#xff0c;較 2020 年增長了 15…

AI_RAG

一.為什么需要RAG&#xff08;AI幻覺&#xff09;大模型LLM在某些情況下給出的回答很可能錯誤的&#xff0c;涉及虛構甚至是故意欺騙的信息。二.什么是RAGRAG是一種結合“信息檢索”和“文本生成”的技術&#xff0c;旨在提升生成式AI模型的準確性和可靠性。它通過以下兩個核心…

LeetCode111~130題解

LeetCode111.二叉樹的最小深度&#xff1a; 題目描述&#xff1a; 給定一個二叉樹&#xff0c;找出其最小深度。 最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。 說明&#xff1a;葉子節點是指沒有子節點的節點。 示例 1&#xff1a; 輸入&#xff1a;root …

n8n飛書webhook配置(飛書機器人、飛書bot、feishu bot)Crypto節點、js timestamp代碼、Crypto node

自定義機器人使用指南 利用 n8n 打造飛書 RSS 推送機器人 文章目錄自定義機器人使用指南注意事項功能介紹在群組中添加自定義機器人操作步驟邀請自定義機器人進群。- 進入目標群組&#xff0c;在群組右上角點擊更多按鈕&#xff0c;并點擊 設置。- 在右側 設置 界面&#xff0…

nhdeep檔案管理工具軟件官網

歡迎訪問nhdeep官網&#xff1a; www.nhdeep.com NHDEEP提供一系列專業的單機版檔案管理工具&#xff0c;滿足不同場景下的檔案管理需求&#xff0c;無需網絡連接&#xff0c;數據安全可靠。所有工具均提供免費試用版下載。 檔案綜合管理系統單機版:全面的檔案管理解決方案&a…

RocketMQ節點部署計算方案

節點計算公式 業務場景 預期峰值TPS&#xff1a;200,000 單組容量&#xff1a;40K TPS 容災要求&#xff1a;同城雙機房 nameServer節點數max(3, (15/50) 1) max(3, 0.3 1) max(3, 1.3) 3 Broker節點數ceil(200,000 / 40,000) 5組 總節點數 NameServer節點Broker組數(Mas…

MyBatis聯合查詢 - XML篇

文章目錄數據庫設計MyBatis 配置MyBatis 映射文件Mapper 接口總結數據庫設計 建表 SQL CREATE TABLE user (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL );CREATE TABLE order (id INT PRIMARY KEY AUTO_INCREMENT,user_id INT NOT NULL,order_no VARCHAR(…

Kubelet 探針如何選擇 IP:status.PodIP 溯源與“同 Pod 兩個 IP“現象解析

背景與現象同一個 Pod 的 readiness 和 liveness 探針日志顯示連接的 IP 不一致&#xff08;例如 10.10.6.10:9999 與 10.10.6.32:9999&#xff09;。本文從 kubelet 源碼入手&#xff0c;解釋探針目標 IP 的來源、為何會出現兩個不同 IP&#xff0c;并給出建議與驗證方法。在如…

Arm Development Studio 安全通告:CVE-2025-7427

安全之安全(security)博客目錄導讀 目錄 一、概述 二、CVE 詳情 三、受影響產品 四、建議 五、致謝 六、版本歷史 一、概述 ARM已知悉一個影響 Arm Development Studio 的安全漏洞&#xff0c;該漏洞可能允許攻擊者執行 DLL 劫持攻擊&#xff08;DLL hijacking attack&…

C#異步編程雙利器:異步Lambda與BackgroundWorker實戰解析

**摘要&#xff1a;**深入剖析兩種異步編程范式&#xff0c;解決GUI線程阻塞難題 一、異步Lambda表達式&#xff1a;事件處理的輕量化利器 核心價值&#xff1a;簡化事件響應中的異步操作&#xff0c;避免UI線程阻塞 ? 典型應用場景&#xff08;WPF示例&#xff09;&#xff1…

yolo world (1): 論文解讀

YOLO 系列檢測器以其高效性和實用性而聞名。然而,它們依賴于預定義和訓練的目標類別,這限制了其在開放場景中的適用性。為了解決這一限制,我們提出了 YOLO-World,這是一種創新的方法,通過視覺-語言建模和大規模數據集預訓練,增強了 YOLO 的開放詞匯檢測能力。具體來說,我…

【JVM】深入解析Java虛擬機

目錄 1. 區分JDK&#xff0c;JRE 和 JVM 1.1 JVM 1.2 JRE 1.3 JDK 1.4 關系總結 2. 跨平臺性 3. JVM中的內存劃分 4. JVM的類加載機制 5. 雙親委派模型 6. 垃圾回收機制&#xff08;GC&#xff09; 6.1 識別垃圾 6.1.1 單個引用 6.1.2 多個引用 6.2 釋放垃圾 6.…

98-基于Python的網上廚房美食推薦系統

基于Python的網上廚房美食推薦系統 - 技術分享博客 &#x1f4cb; 目錄 項目概述技術棧系統架構核心功能實現數據庫設計推薦算法數據可視化部署與優化項目特色總結與展望 &#x1f3af; 項目概述 項目背景 隨著生活節奏的加快&#xff0c;越來越多的人開始關注美食制作&…

創建MyBatis-Plus版的后端查詢項目

記得編碼和maven庫的檢測&#xff01;&#xff01;&#xff01; 1、maven庫導入包<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupI…