C++11--(1)

目錄

1.列表初始化

{}初始化

C++98中

C++11中

內置置類型和自定義類型

創建對象也適用

std::initializer_list

2.變量類型推導

auto

C++98

C++11

decltype

nullptr

3.范圍for循環

4.STL中一些變化

array

1.創建和初始化

2.訪問元素

?編輯

3.修改操作

4.支持迭代器

forward_list

1.創建和初始化

2.訪問元素

3.修改操作

4.支持迭代器

5.右值引用和移動語義

左值引用和右值引用

左值:

右值:

C++11進一步細分:

使用場景

1.函數重載

2.移動語義 (移動構造)

移動構造的觸發場景

a. 顯式使用 std::move

b.函數返回臨時對象

c.接收返回值的構造

d.標準庫容器操作

3. 完美轉發

4.特殊案例

返回左值引用的函數

5.左值與右值的對比

6.左值引用與右值引用的對比

7.左值引用的短板

用右值引用和移動語義可以解決上述問題:

8.右值引用引用引用左值


1.列表初始化

{}初始化

C++98中
標準允許使用花括號 {} 對數組或者結構體元素進行統一的列表初始值設定
struct Point
{int _x;int _y;
};int main()
{int array1[] = { 1, 2, 3, 4, 5 };int array2[5] = { 0 };Point p = { 1, 2 };return 0;
}
C++11中
內置置類型和自定義類型

擴大了用大括號括起的列表(初始化列表)的使用范圍,使其可用于所有的內置類型和用戶自定義的類型,使用初始化列表時,可添加等號(=),也可不添加

struct Point
{int _x;int _y;
};int main()
{int x1 = 1;int x2{ 2 };int array1[] = { 1, 2,3 ,4, 5 };int array2[]{ 1,2,3,4,5 }; // 可加等號,也可不加Point p{ 1, 2 };// c++11中列表初始化也可以適用于new表達式中int* pa = new int[4] {0};return 0;
}
創建對象也適用
class Date
{
public:Date(int year, int month, int day):_year(year), _month(month), _day(day){cout << "Date(int year, int month, int day)" << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2022, 1, 1); // 舊時用法// C++11支持的列表初始化,這里會調用構造函數初始化Date d2{ 2022, 1, 2 };Date d3 = { 2022, 1, 3 }; // 等號可用可不用return 0;
}

std::initializer_list

int main()
{// the type of il is an initializer_list auto il = { 10, 20, 30 };cout << typeid(il).name() << endl;return 0;
}

std::initializer_list 一般是作為構造函數的參數 C++11 STL 中的不少容器就增加std::initializer_list作為參數的構造函數,這樣初始化容器對象就更方便了。
也可以作為 operator= 的參數,這樣就可以用大括號賦值

int main()
{vector<int> v = { 1,2,3,4 };list<int> lt = { 1,2 };// 這里{"sort", "排序"}會先初始化構造一個pair對象map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };// 使用大括號對容器賦值v = { 10, 20, 30 };return 0;
}

2.變量類型推導

auto

C++98
C++98 auto 是一個存儲類型的說明符,表明變量是局部自動存儲類型,但是局部域中定義局部的變量默認就是自動存儲類型,所以auto 就沒什么價值了。
int main() {auto int x = 10;  // C++98: auto 表示 x 是自動存儲類型(默認就是 auto,所以多余)int y = 20;       // 默認就是 auto,等同于 auto int y = 20;return 0;
}
結論:auto 在 C++98 中幾乎沒用,因為局部變量默認就是 auto。
C++11
C++11 中廢棄 auto 原來的用法,將 其用于實現自動類型推斷。這樣要求必須進行顯示初始化,讓編譯器將定義對象的類型設置為初 始化值的類型
C++11 廢棄了 auto 的舊用法,并賦予它 自動類型推斷 的功能:
1.auto 可以讓編譯器自動推斷變量的類型,但必須 顯式初始化(即必須賦值)。
2.適用于復雜類型、模板、迭代器等場景,減少代碼冗余。
int main() {// 基本類型auto x = 10;          // x 的類型是 int(編譯器自動推斷)auto y = 3.14;        // y 的類型是 doubleauto name = "Alice";  // name 的類型是 const char*// STL 容器(避免寫冗長的類型)std::vector<std::string> names = { "Alice", "Bob", "Charlie" };auto it = names.begin();  // it 的類型是 std::vector<std::string>::iterator// 范圍 for 循環(C++11 新增)for (auto& n : names) {   // n 的類型自動推斷為 std::string&std::cout << n << "\n";}return 0;
}

decltype

關鍵字 decltype 將變量的類型聲明為表達式指定的類型
template<class T1, class T2>
void F(T1 t1, T2 t2)
{decltype(t1 * t2) ret;cout << typeid(ret).name() << endl;
}int main()
{const int x = 1;double y = 2.2;decltype(x * y) ret; // ret的類型是doubledecltype(&x) p;      // p的類型是int*cout << typeid(ret).name() << endl;cout << typeid(p).name() << endl;F(1, 'a');return 0;
}

nullptr

由于 C++ NULL 被定義成字面量 0 ,這樣就可能回帶來一些問題,因為 0 既能指針常量,又能表示整形常量。所以出于清晰和安全的角度考慮,C++11 中新增了 nullptr ,用于表示空指針。

3.范圍for循環

范圍?for?循環是 C++11 引入的一種簡化遍歷容器(如數組、vectorlist?等)的語法,它可以自動迭代容器中的所有元素,無需手動管理迭代器或下標。

#include <iostream>int main() 
{int arr[] = {1, 2, 3, 4, 5};// 使用范圍 for 遍歷數組for (auto num : arr) // num 會自動推斷為 int{  std::cout << num << " ";}// 輸出:1 2 3 4 5return 0;
}

應用范圍很廣,比起其他的遍歷方式,其簡單又便捷

4.STL中一些變化

STL新增了一些容器(上圖圈出來的)

array

std::array?是 C++11 引入的一個固定大小的順序容器,它結合了 C 風格數組的性能和標準容器的便利接口。

與普通數組做比較:

1.創建和初始化
int main() 
{// 創建并初始化std::array<int, 5> arr1 = { 1, 2, 3, 4, 5 };// 統一初始化 (C++11) -- 列表初始化std::array<int, 3> arr2{7, 8, 9};// 默認初始化 (元素值未定義)std::array<double, 4> arr3;// 全部初始化為0std::array<int, 5> arr4{};return 0;
}
2.訪問元素
int main()
{std::array<int, 5> nums = { 10, 20, 30, 40, 50 };// 使用下標訪問 (不檢查邊界)int x = nums[2];  // 30// 使用at()訪問 (檢查邊界)int y = nums.at(3);  // 40// nums.at(5) 會拋出 std::out_of_range 異常// 訪問首尾元素int first = nums.front();  // 10int last = nums.back();    // 50// 打印出來std::cout << x << " " << y << " " << first << " " << last << std::endl;// 使用迭代器for (auto it = nums.begin(); it != nums.end(); ++it) {std::cout << *it << " ";}return 0;
}
3.修改操作
int main()
{std::array<int, 5> nums{1, 2, 3, 4, 5};// 填充值nums.fill(10);  // 所有元素變為10// 交換兩個arraystd::array<int, 5> other{5, 4, 3, 2, 1};nums.swap(other);  // nums和other內容交換return 0;
}
4.支持迭代器
int main()
{std::array<std::string, 3> colors{"red", "green", "blue"};// 正向迭代for (auto it = colors.begin(); it != colors.end(); ++it) {std::cout << *it << " ";}// 反向迭代for (auto rit = colors.rbegin(); rit != colors.rend(); ++rit) {std::cout << *rit << " ";}// 范圍for循環 (C++11)for (const auto& color : colors) {std::cout << color << " ";}return 0;
}

forward_list

std::forward_list?是 C++11 引入的單向鏈表容器,比?std::list?更節省內存,但功能稍有限制。

與?std::list?的比較:

1.創建和初始化
int main() 
{// 創建空鏈表std::forward_list<int> flist1;// 創建并初始化std::forward_list<int> flist2 = { 1, 2, 3, 4, 5 };// 指定大小和默認值std::forward_list<int> flist3(5, 100); // 5個元素,每個都是100return 0;
}
2.訪問元素
int main()
{std::forward_list<int> nums = { 10, 20, 30, 40, 50 };// 訪問第一個元素int first = nums.front();  // 10// 不能直接訪問最后一個元素(需要遍歷)// nums.back() 不存在!// 遍歷所有元素for (int num : nums) {std::cout << num << " ";}return 0;
}
3.修改操作
int main()
{std::forward_list<int> nums = { 1, 2, 3 };// 在前面插入元素nums.push_front(0);  // 現在: 0, 1, 2, 3// 刪除第一個元素nums.pop_front();    // 現在: 1, 2, 3// 在特定位置后插入元素auto it = nums.begin();nums.insert_after(it, 99);  // 現在: 1, 99, 2, 3// 刪除特定位置后的元素nums.erase_after(it);       // 現在: 1, 2, 3return 0;
}
4.支持迭代器
int main()
{std::forward_list<int> flist = { 1, 2, 3, 4, 5 };// 獲取指向第一個元素的迭代器auto begin_it = flist.begin();// 獲取尾后迭代器auto end_it = flist.end();// 傳統方式遍歷for (auto it = flist.begin(); it != flist.end(); ++it) {std::cout << *it << " ";}// 范圍for循環 (推薦)for (const auto& elem : flist) {std::cout << elem << " ";}return 0;
}

5.右值引用和移動語義

傳統的C++語法中就有引用的語法,而C++11中新增了的右值引用語法特性

左值引用和右值引用

左值:

左值是指那些有明確內存地址可以取地址的表達式,通常代表一個持久存在的對象。

特點:

1.可以出現在賦值語句的左側

2.有持久的狀態(超出單個表達式仍然存在)

3.可以取地址(使用&運算符)

int x = 10;    // x是左值
int* p = &x;   // 可以取x的地址
x = 20;        // x可以出現在賦值左側
右值:

右值是指臨時對象即將被銷毀的對象,通常代表一個短暫存在的值。

特點:

1.只能出現在賦值語句的右側

2.通常是臨時對象或字面量

3.不能取地址

int x = 10;        // 10是右值
int y = x + 5;     // (x+5)是右值
std::string s = "hello";  // "hello"是右值
C++11進一步細分:

使用場景

1.函數重載

2.移動語義 (移動構造)
class MyString {
public:// 移動構造函數MyString(MyString&& other) {  // 接受右值引用data = other.data;other.data = nullptr;}private:int* data;
};
移動構造的觸發場景
a. 顯式使用 std::move
vector<string> func() {vector<string> local;return std::move(local);  // 強制移動(但可能阻止RVO)
}
b.函數返回臨時對象
vector<string> getTemp() {return vector<string>{"a", "b", "c"};  // 臨時對象必然移動
}
c.接收返回值的構造
class String {char* data;
public:// 移動構造函數String(String&& other) noexcept : data(other.data) {  // 竊取資源other.data = nullptr;}~String() { delete[] data; }
};String createString() {String temp("hello");return temp;  // 返回值優化或移動
}/// ----------------->>
vector<String> strs = createStrings();  // 移動構造或RVO
d.標準庫容器操作
vector<string> v1 = {"a", "b"};
vector<string> v2;
v2 = std::move(v1);  // 移動賦值
3. 完美轉發
template<typename T>
void relay(T&& arg) {  // 萬能引用process(std::forward<T>(arg));  // 完美轉發
}

1. 萬能引用(Universal Reference)

T&& arg 中的 && 并不總是表示右值引用。當 T 是模板參數時,T&& 是一個"萬能引用",它能綁定到左值或右值
?

int x = 10; 
relay(x); ? ? ?// T被推導為int&,arg綁定到左值
relay(20); ? ? // T被推導為int,arg綁定到右值

2. std::forward 的作用

std::forward<T>(arg) 會根據原始參數的值類別決定轉發方式

????????a.如果原始參數是左值,轉發為左值

????????b.如果原始參數是右值,轉發為右值

4.特殊案例
返回左值引用的函數
int& getRef() { static int x; return x; }int main()
{getRef() = 5;  // 函數調用是左值return 0;
}

getRef() 返回的是變量x的引用,因此整個函數調用表達式可以當作x本身使用,包括:

1.出現在賦值左側

2.取地址

3.綁定到非const左值引用

5.左值與右值的對比

6.左值引用與右值引用的對比

7.左值引用的短板
但是當函數返回對象是一個局部變量,出了函數作用域就不存在了,就不能使用左值引用返回,只能傳值返回。
例如:bit::string to_string(int value) 函數中可以看到,這里只能使用傳值返回,傳值返回會導致至少1 次拷貝構造 ( 如果是一些舊一點的編譯器可能是兩次拷貝構造 )

右值引用和移動語義可以解決上述問題:
bit::string 中增加移動構造 移動構造本質是將參數右值的資源竊取過來,占位已有,那么就不 用做深拷貝了,所以它叫做移動構造,就是竊取別人的資源來構造自己
// 移動構造
string(string&& s):_str(nullptr), _size(0), _capacity(0)
{cout << "string(string&& s) -- 移動語義" << endl;swap(s);
}int main()
{bit::string ret2 = bit::to_string(-1234);return 0;
}
8.右值引用引用引用左值
void push_back(value_type&& val);int main()
{list<YC::string> lt;YC::string s1("1111");// 這里調用的是拷貝構造lt.push_back(s1);// 下面調用都是移動構造lt.push_back("2222");lt.push_back(std::move(s1));return 0;
}// 運行結果:
// string(const string& s) -- 深拷貝
// string(string&& s) -- 移動語義
// string(string&& s) -- 移動語義

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

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

相關文章

Promise的狀態和方法是什么?

Promise 的狀態和方法 1. Promise 的狀態 一個 Promise 可以處于以下三種狀態之一&#xff1a; - Pending&#xff08;待定&#xff09;&#xff1a;初始狀態&#xff0c;表示異步操作正在進行中&#xff0c;Promise 還沒有被解決或拒絕。 - Fulfilled&#xff08;已完成&…

Windows云服務器支持哪些數據庫管理系統?

Windows云服務器因其良好的兼容性和企業級支持&#xff0c;廣泛用于網站托管、企業管理系統、金融應用、數據分析等場景。在這些應用中&#xff0c;數據庫管理系統(DBMS)起著至關重要的作用。Windows 服務器支持多種數據庫&#xff0c;包括關系型數據庫(SQL)和非關系型數據庫(N…

MongoDB 實際工作中應用場景

博主介紹&#xff1a;?全網粉絲5W&#xff0c;全棧開發工程師&#xff0c;從事多年軟件開發&#xff0c;在大廠呆過。持有軟件中級、六級等證書。可提供微服務項目搭建與畢業項目實戰&#xff0c;博主也曾寫過優秀論文&#xff0c;查重率極低&#xff0c;在這方面有豐富的經驗…

03 相機標定圖像采集

學完本文,您將獲取一下技能: 1:如何提升標定質量,如選擇標定板,標定圖像采集的注意事項, 2:實現標定圖像自動篩選的代碼 3:量產場景如何通過一張圖像來標定相機 為了實現良好的標定效果,以下因素在標定數據采集前必須設置得當。 標定板選擇 標定板尺寸準確材料平…

GitHub美化個人主頁3D圖表顯示配置操作

這個功能主要是用的這個開源倉庫&#xff1a;https://github.com/yoshi389111/github-profile-3d-contrib 想看效果的話&#xff0c;我的個人主頁&#xff1a;https://github.com/Sjj1024 開始操作 1.創建自己的github主頁屬性項目——跟你github用戶名一致即可&#xff0c;…

buu-jarvisoj_fm-好久不見52

格式化字符串漏洞題 x等于4x等于4???????x等于4???????x等于4 可以知道是第11個參數&#xff0c;%11$ 定位到這個位置&#xff0c;然后%n往這個位置寫入4 1.先用pwndbg調試得到偏移量 2.查看獲取x的地址 3.構造ROP鏈&#xff0c;發送連接 from pwn import *# …

AwesomeQt分享3(含源碼)

AwesomeQt 這個項目包含了多個Qt組件的使用示例&#xff0c;旨在展示Qt各種強大功能的實現方式。 源碼分享 github: awesome_Qtgitee: 后續同步 項目進度 QCustomPlot曲線控件示例 支持排序和篩選的列表控件示例 支持排序和篩選的表格控件示例 屬性表示例 Dock窗口示例 自繪…

ubuntu 安裝 g++

文章目錄 前提一、安裝 g1.1 安裝1.2 驗證 前提 安裝 tflite_support 報錯 error: subprocess-exited-with-error RuntimeError: Unsupported compiler -- at least C11 support is needed!一、安裝 g 1.1 安裝 # 安裝編譯工具鏈&#xff08;如g&#xff09;和依賴庫 sudo …

【NLP 50、損失函數 KL散度】

目錄 一、定義與公式 1.核心定義 2.數學公式 3.KL散度與交叉熵的關系 二、使用場景 1.生成模型與變分推斷 2.知識蒸餾 3.模型評估與優化 4.信息論與編碼優化 三、原理與特性 1.信息論視角 ?2.優化目標 3.?局限性 四、代碼示例 代碼運行流程 核心代碼解析 抵達夢想靠的不是狂熱…

使用QT畫帶有透明效果的圖

分辨率&#xff1a;24X24 最大圓 代碼: #include <QApplication> #include <QImage> #include <QPainter>int main(int argc, char *argv[]) {QImage image(QSize(24,24),QImage::Format_ARGB32);image.fill(QColor(0,0,0,0));QPainter paint(&image);…

【Unity網絡編程知識】使用Socket實現簡單TCP通訊

1、Socket的常用屬性和方法 創建Socket TCP流套接字 Socket socketTcp new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 1.1 常用屬性 1&#xff09;套接字的連接狀態 socketTcp.Connected 2&#xff09;獲取套接字的類型 socketTcp.So…

青少年編程與數學 02-013 初中數學知識點 02課題、概要

青少年編程與數學 02-013 初中數學知識點 02課題、概要 一、數與代數二、圖形與幾何三、統計與概率四、綜合與實踐五、課程理念與目標 根據2022年版義務教育數學課程標準&#xff0c;初中數學知識點可以總結為以下四大領域。 一、數與代數 數與式 有理數與實數&#xff1a;理解…

深入探索 libarchive

深入探索 libarchive&#xff1a;跨平臺歸檔處理的終極解決方案 一、背景與歷史沿革 1.1 歸檔處理的演進之路 從1979年tar格式的誕生到現代云存儲時代&#xff0c;歸檔技術經歷了四個關鍵階段&#xff1a; Unix時代&#xff1a;tar/cpio主導系統備份互聯網黎明期&#xff1…

2025最新“科研創新與智能化轉型“暨AI智能體開發與大語言模型的本地化部署、優化技術實踐

第一章、智能體(Agent)入門 1、智能體&#xff08;Agent&#xff09;概述&#xff08;什么是智能體&#xff1f;智能體的類型和應用場景、典型的智能體應用&#xff0c;如&#xff1a;Google Data Science Agent等&#xff09; 2、智能體&#xff08;Agent&#xff09;與大語…

Yolo_v8的安裝測試

前言 如何安裝Python版本的Yolo&#xff0c;有一段時間不用了&#xff0c;Yolo的版本也在不斷地發展&#xff0c;所以重新安裝了運行了一下&#xff0c;記錄了下來&#xff0c;供參考。 一、搭建環境 1.1、創建Pycharm工程 首先創建好一個空白的工程&#xff0c;如下圖&…

時尚界正在試圖用AI,創造更多沖擊力

數字藝術正以深度融合的方式&#xff0c;在時尚、游戲、影視等行業實現跨界合作&#xff0c;催生了多樣化的商業模式&#xff0c;為創作者和品牌帶來更多機會&#xff0c;數字藝術更是突破了傳統藝術的限制&#xff0c;以趣味觸達用戶&#xff0c;尤其吸引了年輕一代的消費群體…

藍橋杯省模擬賽 01串個數

問題描述 請問有多少個長度為 24 的 01 串&#xff0c;滿足任意 5 個連續的位置中不超過 3 個位置的值為 1。 所有長度為24的01串組合有2*24種 思路&#xff1a;遍歷所有長度為24的01串組合&#xff0c;選擇出符合題意的 #include<iostream> #include<cmath> us…

【軟考備考】系統架構設計論文完整范文示例

本文由AI輔助創造 題目:基于微服務與云原生的智慧政務平臺架構設計與實踐 摘要(約300字) 本文以某省級智慧政務平臺建設項目為背景,針對傳統政務系統存在的"信息孤島"、擴展性差、維護成本高等問題,提出了一套基于微服務與云原生技術的解決方案。通過領域驅動…

數據庫原理及應用mysql版陳業斌實驗二

&#x1f3dd;?專欄&#xff1a;Mysql_貓咪-9527的博客-CSDN博客 &#x1f305;主頁&#xff1a;貓咪-9527-CSDN博客 “欲窮千里目&#xff0c;更上一層樓。會當凌絕頂&#xff0c;一覽眾山小。” 目錄 實驗二單表查詢 1.實驗數據如下 student 表&#xff08;學生表&#…

SDL —— 將sdl渲染畫面嵌入Qt窗口顯示(附:源碼)

?? SDL/SDL2 相關技術、疑難雜癥文章合集(掌握后可自封大俠 ?_?)(記得收藏,持續更新中…) 效果 使用QWidget加載了SDL的窗口,渲染器使用硬件加速跑GPU的。支持Qt窗口縮放或顯示隱藏均不影響SDL的圖像刷新。 ? 操作步驟 1、在創建C++空工程時加入SDL,引入頭文件時需…