C++11相較于C++98的新特性介紹:列表初始化,右值引用與移動語義

一,列表初始化

1.1C++98中傳統的{}

C++98中一般數組和結構體可以使用{}進行初始化:

struct Date
{int _year;int _month;int _day;
};int main()
{int a[] = { 1,2,3,4,5 };Date _date = { 2025,2,27 };return 0;
}

?1.2C++11中的{}

  1. C++11以后想統一初始化方式,試圖實現一切對象皆可用{}初始化,{}初始化也叫做列表初始化。?
  2. 內置類型支持,自定義類型也支持,自定義類型本質是類型轉換,中間會產生臨時對象,最后優化了以后變成直接構造。?
  3. {}初始化的過程中,可以省略掉=。?
  4. C++11列表初始化的本意是想實現一個大統一的初始化方式,其次他在有些場景下帶來的不少便利,如容器push/inset多參數構造的對象時,{}初始化會方便許多。
class Date
{
public:Date(int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day){cout << "Date(int year, int month, int day)" << endl;}Date(const Date& d):_year(d._year), _month(d._month), _day(d._day){cout << "Date(const Date& d)" << endl;}
private:int _year;int _month;int _day;
};int main()
{int a[] = { 1,2,3,4,5 };Date _date = { 2025,2,27 };const Date& d2 = { 2027,2,29 };//右邊{2027,2,29}是一個臨時對象,需要加上const//也可以不加括號Date d3{ 2028,2,27 };//非{}初始化必須要加上等號Date d4 2025;//編譯器報錯Date d5 = 2025;return 0;
}

1.3C++11中的std::initializer_list?

????????上面的{}初始化已然很方便,但是如果說我們要初始化像vector這樣的對像時,他的參數個數是會發生變化的,顯然僅僅只有上面的{}遠遠無法滿足這種需求。所以c++中就提供了std::initializer_list的類, auto il = { 10, 20, 30 }; // thetype of il is an initializer_list ,這個類的本質是底層開一個數組,將數據拷貝過來,std::initializer_list內部有兩個指針分別指向數組的開始和結束。

這是他的文檔:initializer_list - C++ Reference,std::initializer_list支持迭代器遍歷。?

區別是{}還是initializer_list的方法也很簡單,{}傳入的值個數是固定的,由需要初始化的對象類型決定,里面所有數據的類型可能不同。后者可寫入的值不固定,但類型一定相同。

map<int, string> m{ {1,string("hallo")} };
vector<string> v{ "a","b","c" };

二,右值引用與移動語義?

我們之前學習的是C++98中的引用,比如原本有一個int類型的對象x,那么int& b = x,此時b其實就是x的別名。C++11之后,我們之前學過的這種引用方式被叫做左值引用。需要注意的是,無論是左值引用還是右值引用,本質上都是取別名。?

2.1左值與右值?

左值是一個表示數據的表達式(如變量名或解引用的指針),一般是有持久狀態,存儲在內存中,我
們可以獲取它的地址
,左值可以出現賦值符號的左邊,也可以出現在賦值符號右邊。定義時const
修飾符后的左值,不能給他賦值,但是可以取它的地址。

右值也是一個表示數據的表達式,要么是字面值常量、要么是表達式求值過程中創建的臨時對象
等,右值可以出現在賦值符號的右邊,但是不能出現出現在賦值符號的左邊,右值不能取地址。?

值得一提的是,左值的英文簡寫為lvalue,右值的英文簡寫為rvalue。傳統認為它們分別是left
value、right value 的縮寫。現代C++中,lvalue 被解釋為loactor value的縮寫,可意為存儲在內
存中、有明確存儲地址可以取地址的對象,而 rvalue 被解釋為 read value,指的是那些可以提供
數據值,但是不可以尋址,例如:臨時變量,字面量常量,存儲于寄存器中的變量等,也就是說左
值和右值的核心區別就是能否取地址。

//常見的左值比如:
int p;
const int p1;
int a[10];
char c;
a[0] = 1;
string s("111111111");
s[0] = 'b';//....
//它們都有一個共同的特性:可以取地址//常見的右值比如:
10;
s[0] + a[0];
string("111111111111111");
min(s[0],a[0]);
//它們均是臨時對象,無法取地址

2.2左值引用與右值引用?

Type& x = y;//左值引用
Type&& x = y;//右值引用

同樣,右值引用其實就是給右值取別名。

1.對于左值引用,不可以直接引用右值,引用右值時需要加上const。

int& x = 10;//error
const int& x = 10;//true

2.對于右值引用,當然也不可以直接引用左值,但是可以引用move移動之后的左值。

int x = 10;
int&& y = x;//error
int&& y = std::move(x);//true
//move可以將左值強制類型轉化為右值,是庫里面的一個函數模板,本質內部是進行強制類型轉換,當然他還涉
//及一些引用折疊的知識,我們后面會詳細介紹。

3.需要注意的是變量表達式都是左值屬性,也就意味著一個右值被右值引用綁定后,右值引用變量變量表達式的屬性是左值。

int&& y = 10;//y此時是一個左值

4.語法層面看,左值引用和右值引用都是取別名,不開空間。從匯編底層的角度看無論左值引用還是右值引用,底層都是用指針實現的,沒有本質區別。

2.3引用改變生命周期?

右值引用和帶有const的左值引用都可以延長臨時變量的聲明周期,但后者無法被修改。

std::string s1 = "1111111111";
std::string&& s2 = s1 + s1;
const std::string& s3 = s1 + s1;s2 += "Text";//true
s3 += "Text";//error

?2.4左右值引用的參數匹配

在C++98中,實現一個const左值引用作為參數的函數,傳入左值還是右值都可以匹配?

void f(int& x)
{std::cout << "f函數的左值引用重載(" << x << ")" << std::endl;
}void f(const int& x)
{std::cout << "f函數的const左值引用重載(" << x << ")" << std::endl;
}int main()
{int x = 10;f(x);f(10 + 20);return 0;
}

C++11中,對右值進行了明確定義,此時便可以分擔const左值引用對于右值的引用任務給右值引用。即實參是左值會匹配f(左值引用),實參是const左值會匹配f(const 左值引用),實參是右值會匹配f(右值引用)。?(當然沒有右值引用的重載下還可以通過const左值引用來引用右值)。

void f(int& x)
{std::cout << "f函數的左值引用重載(" << x << ")" << std::endl;
}void f(const int& x)
{std::cout << "f函數的const左值引用重載(" << x << ")" << std::endl;
}void f(int&& x)
{std::cout << "f函數的右值引用重載(" << x << ")" << std::endl;
}int main()
{int x = 10;const int y = 20;f(x);f(y);f(10 + 20);return 0;
}

2.5右值引用和移動語義的使用場景?

2.5.1移動構造與移動賦值?

  1. 1.移動構造函數是一種構造函數,類似拷貝構造函數,移動構造函數要求第一個參數是該類類型的引用,但是不同的是要求這個參數是右值引用,如果還有其他參數,額外的參數必須有缺省值。
  2. 2.移動賦值是一個賦值運算符的重載,他跟拷貝賦值構成函數重載,類似拷貝賦值函數,移動賦值函數要求第一個參數是該類類型的引用,但是不同的是要求這個參數是右值引用。
  3. 3.對于像string/vector這樣的深拷貝的類或者包含深拷貝的成員變量的類,移動構造和移動賦值有意義,因為移動構造和移動賦值的第一個參數都是右值引用的類型,他的本質是要“竊取”引用的右值對象的資源,而不是像拷貝構造和拷貝賦值那樣去拷貝資源,從提高效率。下面ELY::string例實現了移動構造和移動賦值,我們需要結合場景理解。

之前文章中我們自己實現的string類:

namespace ELY
{class string{public:typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}const_iterator begin() const{return _str;}const_iterator end() const{return _str + _size;}string(const char* str = ""):_size(strlen(str)), _capacity(_size){cout << "string(char* str)-構造" << endl;_str = new char[_capacity + 1];strcpy(_str, str);}void swap(string& s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}string(const string& s):_str(nullptr){cout << "string(const string& s) -- 拷貝構造" << endl; reserve(s._capacity);for (auto ch : s){push_back(ch);}}//移動構造string(string&& s){cout << "string(string&& s) -- 移動構造" << endl;swap(s);//這樣寫的原因是因為移動構造底層實現原理與直接和臨時對象交換資源類似}string& operator=(const string& s){cout << "string& operator=(const string& s) -- 拷貝賦值" <<endl;if (this != &s){_str[0] = '\0';_size = 0;reserve(s._capacity);for (auto ch : s){push_back(ch);}}return *this;}~string(){cout << "~string() -- 析構" << endl;delete[] _str;_str = nullptr;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];if (_str){strcpy(tmp, _str);delete[] _str;}_str = tmp;_capacity = n;}}void push_back(char ch){if (_size >= _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;++_size;_str[_size] = '\0';}string& operator+=(char ch){push_back(ch);return *this;}const char* c_str() const{return _str;}size_t size() const{return _size;}private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0;};
}

2.5.2右值引用和移動語義解決傳值返回問題

我們知道,在函數傳參的時候使用左值引用能夠減少拷貝,比如下面通過字符串實現高精度計算的函數:

string AddStrings(string& num1, string& num2) {//原本不加引用時需要拷貝代價巨大string str;int end1 = num1.size() - 1, end2 = num2.size() - 1;// 進位int next = 0;while (end1 >= 0 || end2 >= 0){int val1 = end1 >= 0 ? num1[end1--] - '0' : 0;int val2 = end2 >= 0 ? num2[end2--] - '0' : 0;int ret = val1 + val2 + next;next = ret / 10;ret = ret % 10;str += ('0' + ret);}if (next == 1)str += '1';reverse(str.begin(), str.end());return str;
}int main()
{std::string s1 = "11111";std::string s2 = "22222";std::string s3 = AddStrings(s1, s2);std::cout << s3 << std::endl;return 0;
}

但是此時返回str時,如果str過大,那么s3在接收的時候會進行兩次拷貝構造(在string沒有實現移動構造以及編譯器沒有進行編譯優化的前提下):

這樣子代價特別巨大,但是有了上面的右值引用之后。因為右值是一個臨時對象,我們完全可以走移動構造來完成上面的拷貝構造過程。直接把臨時對象中的資源給搶過來。但是我們不能說將上面AddString的返回值改為string&&,因為str中存儲的資源生命周期在函數的作用域內。無法達到預期效果,我們只有對string類實現了移動構造才能實現搶過來的那一步:

當我們把移動構造屏蔽后,s3接收str會經歷以下過程,走了兩次拷貝構造,等于說進行兩次新的資源構建:

但是我們實現移動構造之后,全程只有移動構造,沒有任何新資源的構建,極大節省了資源消耗:

2.5.3右值引用與移動語義在傳參中的提效

  1. 查看STL文檔我們發現C++11以后容器的push和insert系列的接口否增加的右值引用版本。
  2. 當實參是一個左值時,容器內部繼續調用拷貝構造進行拷貝,將對象拷貝到容器空間中的對象。
  3. 當實參是一個右值,容器內部則調用移動構造,將實參的資源直接掠奪過來構造當前對象

測試代碼:

int main()
{std::list<bit::string> lt;bit::string s1("111111111111111111111");lt.push_back(s1);cout << "*************************" << endl;lt.push_back(bit::string("22222222222222222222222222222"));cout << "*************************" << endl;lt.push_back("3333333333333333333333333333");cout << "*************************" << endl;lt.push_back(move(s1));cout << "*************************" << endl;return 0;
}

運行結果:

2.6類型分類(了解)

  1. C++11以后,進一步對類型進行了劃分,右值被劃分純右值(pure value,簡稱prvalue)和將亡值(expiring value,簡稱xvalue)。
  2. 純右值是指那些字面值常量或求值結果相當于字面值或是一個不具名的臨時對象。如: 42、true、nullptr 或者類似str.substr(1, 2)、str1 + str2 傳值返回函數調用,或者整形a、b、a++,a+b 等。純右值和將亡值C++11中提出的,C++11中的純右值概念劃分等價于C++98中的右值。
  3. 將亡值是指返回右值引用的函數的調用表達式和轉換為右值引用的轉換函數的調用表達,如move(x)、static_cast<X&&>(x)。
  4. 泛左值(generalized value,簡稱glvalue),泛左值包含將亡值和左值。
  5. 有名字,就是glvalue;有名字,且不能被move,就是lvalue;有名字,且可以被move,就是xvalu;沒有名字,且可以被移動,則是prvalue。?

官方文檔:

值類別 - cppreference.com?,????https://en.cppreference.com/w/cpp/language/value_category

2.7引用折疊

1.C++中不能直接定義引用的引用如int& && r = i; 這樣寫會直接報錯,通過模板或 typedef
中的類型操作可以構成引用的引用。

using lref = int&;
using rref = int&&;int main()
{int y = 10;int& &&r = y;//errorlref&& z = y;//truereturn 0;
}

2.對于兩種引用的四種組合,只有&& 與 && 組合時才是右值引用:

lref& x = y;//x類型是int&
lref&& x = y;//x類型是int&
rref& x = y;//x類型是int&
rref&& x = 10;//x類型是int&&
template<class T>
void f1(T& x)
{}template<class T>
void f2(T&& x)
{}
int main()
{int n = 0;//無折疊->類型實例化為int&f1<int>(n);f1<int>(0);//報錯//折疊->類型實例化為int&f1<int&>(n);f1<int&>(0);//報錯//折疊->類型實例化為int&f1<int&&>(n);f1<int&&>(0);//報錯//折疊->示例化為const int&f1<const int&>(n);f1<const int&>(0);//折疊->實例化為const int&f1<const int&&>(n);f1<const int&&>(0);//無折疊->類型實例化為int&&f2<int>(n);//報錯f2<int>(0);//折疊->類型實例化為int&f2<int&>(n);f2<int&>(0);//報錯//折疊->類型實例化為int&&f2<int&&>(n);//報錯f2<int&&>(0);//折疊->示例化為const int&f2<const int&>(n);f2<const int&>(0);//折疊->實例化為const int&&f2<const int&&>(n);//報錯f2<const int&&>(0);return 0;
}
template<class T>
void Function(T&& t)
{int a = 0;T x = a;x++;cout << &a << endl;cout << &x << endl << endl;
}int main()
{//無折疊-模板類型實例化為int&&Function(10);//右值int a = 0;//折疊,因為a為左值,模板類型實例化為int&Function(a);//左值// std::move(a)是右值,推導出T為int,模板實例化為void Function(int&& t)Function(std::move(a)); // 右值const int b = 8;// b是左值,推導出T為const int&,引用折疊,模板實例化為void Function(const int&// 所以Function內部會編譯報錯,x不能++Function(b); // const 左值// std::move(b)右值,推導出T為const int,模板實例化為void Function(const int&&t)// 所以Function內部會編譯報錯,x不能++Function(std::move(b)); // const 右值return 0;
}

我們也稱Function(T&& t)這種為萬能引用,傳左值為左值,而傳右值則為右值。?

2.8完美轉發

我們在實際過程中,可能在函數中再去調用別的函數,比如如下這種情況:

void f1(int& x)
{}void f1(int&& x)
{}template<class T>
void fc(T&& t)
{f1(t);
}
int main()
{int n = 0;fc(n);fc(0);return 0;
}

我們上面也說過,對于int&& x = y;此時的x為左值屬性。我們發現對于上圖中的兩次fc調用,n是左值直到傳到f1時也可以保持其左值屬性不變。但0在傳入fc之后,0是一個右值,一個右值被右值引用綁定后,右值引用變量表達式的屬性是左值,也就是說fc函數中t的屬性是左值。此時便會調用f1的左值引用版本,換言之0在函數傳遞中失去了其本身的右值屬性。如果我們想要保持0自身的右值屬性在傳遞中不丟失,就需要使用完美轉發。

完美轉發:

template <class _Ty>
_Ty&& forward(remove_reference_t<_Ty>& _Arg) noexcept
{ // forward an lvalue as either an lvalue or an rvaluereturn static_cast<_Ty&&>(_Arg);
}

完美轉發forward本質是一個函數模板,他主要還是通過引用折疊的方式實現。此時我們只需要將上面的代碼改為如下格式:

void f1(int& x)
{}void f1(int&& x)
{}template<class T>
void fc(T&& t)
{f1(forward<T>(t));
}
int main()
{int n = 0;fc(n);fc(0);return 0;
}

這樣0在經fc傳入f1時便會調用右值引用版本的重載。保留了其本身的右值屬性。?

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

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

相關文章

序列化是什么?常見的序列化方式有哪些?什么時候我們會用到序列化?

序列化&#xff08;Serialization&#xff09;是指將對象的狀態信息轉換為可以存儲或傳輸的形式&#xff08;如字節序列、XML 文檔、JSON 字符串等&#xff09;的過程。反序列化則是序列化的逆過程&#xff0c;它將存儲或接收到的字節序列、XML 文檔、JSON 字符串等轉換回對象的…

Python解決“比賽配對”問題

Python解決“比賽配對”問題 問題描述測試樣例解決思路代碼 問題描述 小R正在組織一個比賽&#xff0c;比賽中有 n 支隊伍參賽。比賽遵循以下獨特的賽制&#xff1a; 如果當前隊伍數為 偶數&#xff0c;那么每支隊伍都會與另一支隊伍配對。總共進行 n / 2 場比賽&#xff0c;…

uniapp中使用leaferui使用Canvas繪制復雜異形表格的實現方法

需求&#xff1a; 如下圖&#xff0c;要實現左圖的樣式&#xff0c;先實現框架&#xff0c;文字到時候 往里填就行了&#xff0c;原來的解決方案是想用css,html來實現&#xff0c;發現實現起來蠻麻煩的。我也沒找到合適的實現方法&#xff0c;最后換使用canvas來實現&#xff…

大模型與呼叫中心融合:未來發展的潛力何在?

大模型與呼叫中心的結合&#xff0c;為企業帶來了前所未有的發展機遇。通過提升服務效率、優化營銷效果、降低運營成本、增強數據管理與分析能力、提升客戶體驗以及推動行業創新與變革&#xff0c;大模型呼叫中心正在重塑客戶服務與營銷的未來。 大模型與呼叫中心的結合具有巨…

vue3+ts+uniapp+unibest 微信小程序(第二篇)—— 圖文詳解自定義背景圖頁面布局、普通頁面布局、分頁表單頁面布局

文章目錄 簡介一、自定義背景圖布局1.1 效果預覽1.2 實現思路1.3 custom-page 組件全量代碼1.4 頁面使用 二、普通頁面布局2.1 效果預覽2.2 實現思路2.3 公共樣式部分2.4 頁面使用 三、分頁表單頁面布局3.1 效果預覽3.2 實現思路3.3 頁面代碼 簡介 開發工具&#xff1a;VsCode…

華為交換機堆疊方法

堆疊配置&#xff1a; 先把接口shutdown 第一臺&#xff1a; int stack-port 0/1 port interface XGigabitEthernet0/0/3 enable y qu int stack-port 0/2 port interface XGigabitEthernet0/0/4 enable y qu stack slot 0 priority 200 y 第二臺&#xff1a; int stack…

AI革命下的多元生態:DeepSeek、ChatGPT、XAI、文心一言與通義千問的行業滲透與場景重構

前言 人工智能技術的爆發式發展催生了多樣化的AI模型生態&#xff0c;從通用對話到垂直領域應用&#xff0c;從數據挖掘到創意生成&#xff0c;各模型憑借其獨特的技術優勢與場景適配性&#xff0c;正在重塑全球產業格局。本文將以DeepSeek、ChatGPT、XAI&#xff08;可解釋人…

nginx 配置https

參考文檔&#xff1a;nginx 文檔 -- nginx官網|nginx下載安裝|nginx配置|nginx教程 配置 HTTPS 服務器 HTTPS 服務器優化 SSL 證書鏈 單個 HTTP/HTTPS 服務器 基于名稱的 HTTPS 服務器 具有多個名稱 的 SSL 證書 服務器名稱指示 兼容性 要配置 HTTPS 服務器&#xff0c;ssl…

python-leetcode-乘積最大子數組

152. 乘積最大子數組 - 力扣&#xff08;LeetCode&#xff09; class Solution:def maxProduct(self, nums: List[int]) -> int:if not nums:return 0max_prod nums[0]min_prod nums[0]result nums[0]for i in range(1, len(nums)):if nums[i] < 0:max_prod, min_prod…

前端或者后端通常用到數組使用方式

第一個是:Array.from() 將具有length屬性或者可迭代的對象轉化為數組 Array.from(abcdef) // 返回值[a1, b1, c1, d1, e1, f1] Array.from(new Map([[b1, 1 ], [a1, 2 ]])) Array.from(new Set([ 1 , 2 , 3 ])) 第二個是:Array.reduce() 遍歷數組,將函數的返回值,存儲到累加器中…

最大子數組和力扣--53

目錄 題目 思路 代碼 題目 給你一個整數數組 nums &#xff0c;請你找出一個具有最大和的連續子數組&#xff08;子數組最少包含一個元素&#xff09;&#xff0c;返回其最大和。 子數組是數組中的一個連續部分。 示例 1&#xff1a; 輸入&#xff1a;nums [-2,1,-3,4,-1…

JavaScript 深淺拷貝全面解析

在 JavaScript 中&#xff0c;深淺拷貝是處理對象復制的重要概念。它們的核心區別在于對 引用類型數據 的處理方式&#xff0c;理解這一點對避免程序中的意外數據污染至關重要。 一、核心概念解析 1. 基本類型 vs 引用類型 基本類型&#xff1a;Number, String, Boolean, null…

【大模型】大模型推理能力深度剖析:從通用模型到專業優化

大模型推理能力深度剖析&#xff1a;從通用模型到專業優化 大模型推理能力深度剖析&#xff1a;從通用模型到專業優化一、通用語言模型與推理模型的區別&#xff08;一&#xff09;通用語言模型&#xff1a;多任務的“萬金油”&#xff08;二&#xff09;推理模型&#xff1a;復…

RISC-V架構的平臺級中斷控制器(PLIC:platform-level interrupt controller)詳解

英文縮寫 英文縮寫中文含義PLICplatform-level interrupt controller&#xff0c;平臺級中斷控制器SMTsimultaneous multi-threading&#xff0c;并發多線程HARTRISC-V架構中的硬件線程SMTsimultaneous multi-threading&#xff0c;多線程執行M-MODEmachine mode&#xff0c;機…

[Web 安全] PHP 反序列化漏洞 —— PHP 序列化 反序列化

關注這個專欄的其他相關筆記&#xff1a;[Web 安全] 反序列化漏洞 - 學習筆記-CSDN博客 0x01&#xff1a;PHP 序列化 — Serialize 序列化就是將對象的狀態信息轉化為可以存儲或傳輸的形式的過程&#xff0c;在 PHP 中&#xff0c;通常使用 serialize() 函數來完成序列化的操作…

航空裝配自動化神器Ethercat轉profient網關搭配機器人精準控制

生產管理系統通過網關與裝配機器人連接&#xff0c;加快航空器機身的裝配速度&#xff0c;減少人為誤差。 航空制造對裝配線的精度和效率有著極高的要求。某航空制造廠使用的耐達訊Profinet轉EtherCAT協議網關NY-PN-ECATM&#xff0c;將其生產管理系統與裝配機器人連接&#xf…

什么是MySql的主從復制(主從同步)?

主頁還有其他面試題總結&#xff0c;有需要的可以去看一下&#xff0c;喜歡的就留個三連再走吧~ 1.什么是MySql的主從復制原理&#xff1f; 主從復制的核心就是二進制binlog&#xff08;DDL&#xff08;數據定義語言&#xff09;語句和DML&#xff08;數據操縱語言&#xff09…

自然語言處理:初識自然語言處理

介紹 大家好&#xff0c;博主又來給大家分享知識了。從這次開始&#xff0c;博主給大家分享自然語言處理這個領域的內容。這也是博主非常感興趣的研究領域。 最開始&#xff0c;博主計劃在自然語言處理系列的第一篇博文中&#xff0c;和大家聊聊文本規范化這個話題。畢竟在自…

【保姆級視頻教程(二)】YOLOv12訓練數據集構建:標簽格式轉換-劃分-YAML 配置 避坑指南 | 小白也能輕松玩轉目標檢測!

【2025全站首發】YOLOv12訓練數據集構建&#xff1a;標簽格式轉換-劃分-YAML 配置 避坑指南 | 小白也能輕松玩轉目標檢測&#xff01; 文章目錄 1. 數據集準備1.1 標簽格式轉換1.2 數據集劃分1.3 yaml配置文件創建 2. 訓練驗證 1. 數據集準備 示例數據集下載鏈接&#xff1a;P…

【人工智能】藍耘智算平臺盛大發布DeepSeek滿血版:開創AI推理體驗新紀元

&#x1f4dd;個人主頁&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的關注 &#x1f339;&#x1f339; ? 藍耘智算平臺 藍耘智算平臺核心技術與突破元生代推理引擎快速入門&#xff1a;三步調用大模型接口&#xff0c;OpenAI SDK無縫兼容實戰用例文…