最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++11右值引用與Lambda表達(dá)式的使用

 更新時(shí)間:2025年07月28日 14:55:58   作者:QQ_437664314  
C++11引入右值引用,實(shí)現(xiàn)移動(dòng)語(yǔ)義提升性能,支持資源轉(zhuǎn)移與完美轉(zhuǎn)發(fā);同時(shí)引入Lambda表達(dá)式,簡(jiǎn)化匿名函數(shù)定義,通過捕獲列表和參數(shù)列表靈活處理變量

C++11新特性

右值引用和移動(dòng)語(yǔ)義

傳統(tǒng)的C++語(yǔ)法中就有引用的語(yǔ)法,而C++11中新增了的右值引用語(yǔ)法特性,所以從現(xiàn)在開始我們之前學(xué)習(xí)的引用就叫做左值引用。無論左值引用還是右值引用,都是給對(duì)象取別名。那么什么是左值?什么是左值引用?

左值是一個(gè)表示數(shù)據(jù)的表達(dá)式(如變量名或解引用的指針),我們可以獲取它的地址+可以對(duì)它賦值,左值可以出現(xiàn)賦值符號(hào)的左邊,右值不能出現(xiàn)在賦值符號(hào)左邊。定義時(shí)const修飾符后的左值,不能給他賦值,但是可以取它的地址。左值引用就是給左值的引用,給左值取別名。

左值 / 右值

右值也是一個(gè)表示數(shù)據(jù)的表達(dá)式,如:字面常量、表達(dá)式返回值,函數(shù)返回值(這個(gè)不能是左值引用返回)等等,右值可以出現(xiàn)在賦值符號(hào)的右邊,但是不能出現(xiàn)出現(xiàn)在賦值符號(hào)的左邊,右值不能取地址。

右值引用就是對(duì)右值的引用,給右值取別名。

右值引用特性:

語(yǔ)法:Type&& 變量名= 值;

目的:

識(shí)別并利用臨時(shí)對(duì)象的資源:避免不必要的深拷貝。

實(shí)現(xiàn)移動(dòng)語(yǔ)義:轉(zhuǎn)移資源所有權(quán)而非復(fù)制。

完美轉(zhuǎn)發(fā):在模板中保持參數(shù)的值類別。

  • std::move():將左值轉(zhuǎn)為右值
  • std::forward():完美轉(zhuǎn)發(fā)參數(shù)

左值:有名稱、有地址、可被取地址的持久對(duì)象

int main(){
int* p = new int(0);	// 以下的p、b、c、*p都是左值
int b = 1;				//  b 是左值,1是右值
int *ptr=&b;			// 可以取b的地址,說明b是左值
const int c = 2;
	int*& rp = p;	    // 以下幾個(gè)是對(duì)上面左值的左值引用
 	int& rb = b;
	const int& rc = c;
 	int& pvalue = *p;
 return 0;}

右值 : 臨時(shí)對(duì)象、字面量、即將銷毀的對(duì)象

std::move(x);    // 返回右值引用
double x = 1.1, y = 2.2;
10; 			 // 字面量是右值
x + y;  	     // 表達(dá)式結(jié)果是右值
fmin(x, y);  	 //函數(shù)
	 			 // 以下幾個(gè)都是對(duì)右值的右值引用
	int&& rr1 = 10; 	 // 右值引用綁定到字面量(右值)
    int& err = 42;       // 錯(cuò)誤:左值引用不能直接綁定到右值
 	double&& rr2 = x + y;// x+y是右值(臨時(shí)計(jì)算結(jié)果)
 	double&& rr3 = fmin(x, y);
 						 // 這里編譯會(huì)報(bào)錯(cuò):error C2106: “=”: 左操作數(shù)必須為左值
		10 = 1;
 		x + y = 1;
 		fmin(x, y) = 1;

常見的左值和右值

左值示例:

  • 變量名:int x; 中的 x
  • 函數(shù)返回的左值引用:std::getline() 返回的 std::istream&
  • 數(shù)組元素:arr[0]
  • 解引用指針:*ptr

右值示例:

  • 字面量:42, true
  • 臨時(shí)對(duì)象:std::string("temp")
  • 表達(dá)式結(jié)果:x + 1, func()(如果func()返回值類型)
  • 將亡值:std::move(x) 返回的右值引用

int a = 10;
// 左值引用 引用 左值
int& ra = a;
// 右值引用 引用 右值
int&& rr = 10;

需要注意的是右值是不能取地址的,但是給右值取別名后,會(huì)導(dǎo)致右值被存儲(chǔ)到特定位置,且可以取到該位置的地址,也就是說例如:不能取字面量10的地址,但是rr1引用后,可以對(duì)rr1取地址,也可以修改rr1。

如果不想rr1被修改,可以用const int&& rr1 去引用,是不是感覺很神奇,這個(gè)了解一下實(shí)際中右值引用的使用場(chǎng)景并不在于此,這個(gè)特性也不重要。

int main(){
 double x = 1.1, y = 2.2;
 int&& rr1 = 10;
 const double&& rr2 = x + y;
 rr1 = 20;
 rr2 = 5.5;  // 報(bào)錯(cuò)
return 0;
 }

移動(dòng)語(yǔ)義

移動(dòng)語(yǔ)義允許將資源(如動(dòng)態(tài)分配的內(nèi)存)從一個(gè)對(duì)象轉(zhuǎn)移到另一個(gè)對(duì)象,而無需進(jìn)行深拷貝,從而顯著提高性能。

移動(dòng)構(gòu)造函數(shù)

移動(dòng)構(gòu)造函數(shù)接受一個(gè)右值引用作為參數(shù),用于從臨時(shí)對(duì)象中 “轉(zhuǎn)移” 資源。

// 移動(dòng)構(gòu)造函數(shù)
Date(Date&& other) noexcept
    : year(other.year), month(other.month), day(other.day) {
     other.year = nullptr;  // 轉(zhuǎn)移資源所有權(quán)
     std::cout << "移動(dòng)構(gòu)造: " << (year ? *year : 0) 
       << "-" << month << "-" << day << std::endl;
    }

移動(dòng)復(fù)制運(yùn)算符

移動(dòng)賦值運(yùn)算符用于從右值對(duì)象轉(zhuǎn)移資源。

// 移動(dòng)賦值運(yùn)算符
Date& operator=(Date&& other) noexcept {
      if (this != &other) {
          delete year;       // 釋放當(dāng)前資源
          year = other.year; // 轉(zhuǎn)移資源
          month = other.month;
          day = other.day;
          other.year = nullptr; // 重置源對(duì)象
        }
      std::cout << "移動(dòng)賦值: " << (year ? *year : 0) 
           << "-" << month << "-" << day << std::endl;
        return *this;
    }

move

將一個(gè)左值強(qiáng)制轉(zhuǎn)換為右值引用,從而可以調(diào)用移動(dòng)語(yǔ)義。

Date d1(1,2,3);
Date d2= std::move(d1);  // 調(diào)用移動(dòng)構(gòu)造函數(shù)
// 注意:d1的資源已被轉(zhuǎn)移,此時(shí)d1處于有效但未指定的狀態(tài)

完美轉(zhuǎn)發(fā)

完美轉(zhuǎn)發(fā)允許函數(shù)模板將參數(shù)以原始的值類別轉(zhuǎn)發(fā)給其他函數(shù),避免不必要的拷貝或轉(zhuǎn)換。

萬能引用與forward

在模板中,使用T&&聲明的參數(shù)可以綁定到任何類型的參數(shù)(左值或右值)。forward在轉(zhuǎn)發(fā)過程中保持參數(shù)的原始值類別。

template<typename T>
void func1(T&& arg) {
    // 如果arg是右值,轉(zhuǎn)發(fā)為右值;如果是左值,轉(zhuǎn)發(fā)為左值
    func2(std::forward<T>(arg));
}
// 示例調(diào)用
void func(int& x) { std::cout << "左值" << std::endl; }
void func(int&& x) { std::cout << "右值" << std::endl; }

int main() {
    int x = 10;
    func1(x);     // 轉(zhuǎn)發(fā)為左值,調(diào)用func(int&)
    func1(20);    // 轉(zhuǎn)發(fā)為右值,調(diào)用func(int&&)
    return 0;
}

完整代碼:

class Date {
public:
    // 默認(rèn)構(gòu)造函數(shù)
    Date(int y = 2000, int m = 1, int d = 1) 
        : year(new int(y)), month(m), day(d) {
        std::cout << "構(gòu)造: " << *year << "-" << month << "-" << day << std::endl;
    }

    // 拷貝構(gòu)造函數(shù)
    Date(const Date& other) 
        : year(new int(*other.year)), month(other.month), day(other.day) {
        std::cout << "拷貝構(gòu)造: " << *year << "-" << month << "-" << day << std::endl;
    }

    // 釋放原對(duì)象的資源,防止析構(gòu)時(shí)重復(fù)釋放
    Date(Date&& other) noexcept
        : year(other.year), month(other.month), day(other.day) {
        other.year = nullptr;  // 轉(zhuǎn)移資源所有權(quán)
        std::cout << "移動(dòng)構(gòu)造: " << (year ? *year : 0) << "-" << month << "-" << day << std::endl;
    }

    // 拷貝賦值運(yùn)算符
    Date& operator=(const Date& other) {
        if (this != &other) {
            delete year;
            year = new int(*other.year);
            month = other.month;
            day = other.day;
        }
        std::cout << "拷貝賦值: " << *year << "-" << month << "-" << day << std::endl;
        return *this;
    }

    // 移動(dòng)賦值運(yùn)算符
    Date& operator=(Date&& other) noexcept {
        if (this != &other) {
            delete year;       // 釋放當(dāng)前資源
            year = other.year; // 轉(zhuǎn)移資源
            month = other.month;
            day = other.day;
            other.year = nullptr; // 重置源對(duì)象
        }
        std::cout << "移動(dòng)賦值: " << (year ? *year : 0) << "-" << month << "-" << day << std::endl;
        return *this;
    }

    // 析構(gòu)函數(shù)
    ~Date() {
        delete year;
        std::cout << "析構(gòu): " << (year ? *year : 0) << "-" << month << "-" << day << std::endl;
    }

    // 獲取日期字符串
    std::string toString() const {
        return year ? 
            std::to_string(*year) + "-" + std::to_string(month) + "-" + std::to_string(day) :
            "invalid date";
    }
    private:
    int* year;  // 動(dòng)態(tài)分配資源
    int month;
    int day;
};

// 完美轉(zhuǎn)發(fā)示例
template<typename T>
void setDate(T&& date) {
    Date storage = std::forward<T>(date); // 保持原始值類別
    std::cout << "存儲(chǔ)日期: " << storage.toString() << std::endl;
}

int main() {
    // 移動(dòng)構(gòu)造示例
    Date d1(2025, 10, 1);
    Date d2(std::move(d1));  // 調(diào)用移動(dòng)構(gòu)造函數(shù)
    std::cout << "d1: " << d1.toString() << std::endl; // 輸出: invalid date
    std::cout << "d2: " << d2.toString() << std::endl; // 輸出: 2023-10-1

    // 移動(dòng)賦值示例
    Date d3(2025, 1, 1);
    d2 = std::move(d3);      // 調(diào)用移動(dòng)賦值運(yùn)算符
    std::cout << "d2: " << d2.toString() << std::endl; // 輸出: 2024-1-1
    std::cout << "d3: " << d3.toString() << std::endl; // 輸出: invalid date

    // 完美轉(zhuǎn)發(fā)示例
    Date d4(2025, 5, 15);
    setDate(d4);             // 左值參數(shù),調(diào)用拷貝構(gòu)造
    setDate(Date(2025, 10, 1)); // 右值參數(shù),調(diào)用移動(dòng)構(gòu)造

    return 0;
}

Lambda 表達(dá)式詳解

隨著C++語(yǔ)法的發(fā)展,人們開始覺得上面的寫法太復(fù)雜了,每次為了實(shí)現(xiàn)一個(gè)algorithm算法, 都要重新去寫一個(gè)類,如果每次比較的邏輯不一樣,還要去實(shí)現(xiàn)多個(gè)類,特別是相同類的命名,這些都給編程者帶來了極大的不便。因此,在C++11語(yǔ)法中出現(xiàn)了Lambda表達(dá)式。

Lambda 表達(dá)式

int main()
 {
 vector<Goods> v = { { "蘋果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2, 
3 }, { "菠蘿", 1.5, 4 } };
 sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){
 return g1._price < g2._price; });
 sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){
 return g1._price > g2._price; });
 sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){
 return g1._evaluate < g2._evaluate; });
 sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){
 return g1._evaluate > g2._evaluate; });
 }

上述代碼就是使用C++11中的lambda表達(dá)式來解決,可以看出lambda表達(dá)式實(shí)際是一個(gè)匿名函數(shù)。

Lambda 表達(dá)式語(yǔ)法

[capture-list](parameters) mutable -> return-type { body }
  1. 捕獲列表 (capture-list):定義外部變量的訪問方式
  2. 參數(shù)列表 (parameters):與普通函數(shù)參數(shù)類似
  3. mutable 修飾符:允許修改按值捕獲的變量
  4. 返回類型 (return-type):可顯式聲明或自動(dòng)推導(dǎo)
  5. 函數(shù)體 (body):包含實(shí)際執(zhí)行的代碼

注意:

在lambda函數(shù)定義中,參數(shù)列表和返回值類型都是可選部分,而捕捉列表和函數(shù)體可以為空。因此C++11中最簡(jiǎn)單的lambda函數(shù)為:[]{}; 該lambda函數(shù)不能做任何事情。

int main()
 {
 // 最簡(jiǎn)單的lambda表達(dá)式, 該lambda表達(dá)式?jīng)]有任何意義
    []{}; 
// 省略參數(shù)列表和返回值類型,返回值類型由編譯器推導(dǎo)為int
 int a = 3, b = 4;
    [=]{return a + 3; }; 
// 省略了返回值類型,無返回值類型
auto fun1 = [&](int c){b = a + c; }; 
fun1(10)
 cout<<a<<" "<<b<<endl;
 }

通過上述例子可以看出,lambda表達(dá)式實(shí)際上可以理解為無名函數(shù),該函數(shù)無法直接調(diào)用,如果想要直接調(diào)用,可借助auto將其賦值給一個(gè)變量。

捕獲列表說明

捕捉列表描述了上下文中那些數(shù)據(jù)可以被lambda使用,以及使用的方式傳值還是傳引用。

  • [var]:表示值傳遞方式捕捉變量var
  • [=]:表示值傳遞方式捕獲所有父作用域中的變量(包括this)
  • [&var]:表示引用傳遞捕捉變量var
  • [&]:表示引用傳遞捕捉所有父作用域中的變量(包括this)
  • [this]:表示值傳遞方式捕捉當(dāng)前的this指針

注意:

父作用域定義

  • 指包含 lambda 函數(shù)的語(yǔ)句塊(局部作用域)

捕獲列表語(yǔ)法

  • 多捕獲項(xiàng)用逗號(hào)分隔

禁止重復(fù)捕獲

  • 非局部作用域限制
  • 全局/命名空間作用域的 lambda 捕獲列表必須為空

局部變量捕獲限制

  • 只能捕獲父作用域的局部變量或this
  • 禁止捕獲類成員變量(除非通過this

Lambda對(duì)象唯一性

  • 每個(gè)lambda表達(dá)式生成唯一類型
  • 禁止同類型lambda相互賦值(即使捕獲方式相同)

函數(shù)對(duì)象與lambda表達(dá)式

函數(shù)對(duì)象,又稱為仿函數(shù),即可以想函數(shù)一樣使用的對(duì)象,就是在類中重載了operator()運(yùn)算符的類對(duì)象。

class Rate{
public:
 		Rate(double rate): _rate(rate){}
 		double operator()(double money, int year){ 
     return money * _rate * year;}
 private:
 		double _rate;
 	};
 int main(){
 	// 函數(shù)對(duì)象
	double rate = 0.49;
 	Rate r1(rate);
 	r1(10000, 2);
 	// lamber
 	auto r2 = [=](double monty, int year)->double{return monty*rate*year; 
};
 	r2(10000, 2);
 	return 0

從使用方式上來看,函數(shù)對(duì)象與lambda表達(dá)式完全一樣。

函數(shù)對(duì)象將rate作為其成員變量,在定義對(duì)象時(shí)給出初始值即可,lambda表達(dá)式通過捕獲列表可以直接將該變量捕獲到。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • C++常用函數(shù)總結(jié)(algorithm 頭文件)

    C++常用函數(shù)總結(jié)(algorithm 頭文件)

    本文給大家詳細(xì)介紹了algorithm 頭文件中最常用的函數(shù)及其使用方法,當(dāng)然這只是其中的一部分,algorithm 頭文件中還有很多其他的函數(shù),感興趣的朋友一起看看吧
    2023-12-12
  • C++類和對(duì)象之類的6個(gè)默認(rèn)成員函數(shù)詳解

    C++類和對(duì)象之類的6個(gè)默認(rèn)成員函數(shù)詳解

    類是對(duì)某一事物的抽象描述,具體地講類是C++中的一種構(gòu)造的數(shù)據(jù)類型,下面這篇文章主要給大家介紹了關(guān)于C++類和對(duì)象之類的6個(gè)默認(rèn)成員函數(shù)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • C語(yǔ)言中的浮點(diǎn)數(shù)存儲(chǔ)詳解

    C語(yǔ)言中的浮點(diǎn)數(shù)存儲(chǔ)詳解

    這篇文章主要介紹了C語(yǔ)言中的浮點(diǎn)數(shù)存儲(chǔ)詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Matlab 數(shù)字圖像的濾波及邊緣檢測(cè)

    Matlab 數(shù)字圖像的濾波及邊緣檢測(cè)

    本文運(yùn)用文字、代碼以及示例詳細(xì)介紹了數(shù)字圖像的濾波以及圖像的邊緣檢測(cè),需要的朋友可以自己了解一下
    2021-08-08
  • C語(yǔ)言 數(shù)據(jù)結(jié)構(gòu)中求解迷宮問題實(shí)現(xiàn)方法

    C語(yǔ)言 數(shù)據(jù)結(jié)構(gòu)中求解迷宮問題實(shí)現(xiàn)方法

    這篇文章主要介紹了C語(yǔ)言 數(shù)據(jù)結(jié)構(gòu)中求解迷宮問題實(shí)現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Visual Studio調(diào)試C/C++教程指南

    Visual Studio調(diào)試C/C++教程指南

    VisualStudio是微軟開發(fā)的一款集成開發(fā)環(huán)境軟件,本文主要介紹了Visual Studio調(diào)試C/C++教程指南,熟悉地掌握基于VS的C/C++調(diào)試技術(shù),可以大幅提升調(diào)試性能,感興趣的可以了解一下
    2024-06-06
  • c++中創(chuàng)建.in文件的方法步驟

    c++中創(chuàng)建.in文件的方法步驟

    在本篇文章里小編給大家分享了一篇關(guān)于c++中創(chuàng)建.in文件的方法步驟的內(nèi)容以及相關(guān)知識(shí)點(diǎn),需要的朋友們學(xué)習(xí)下。
    2019-07-07
  • C++類型轉(zhuǎn)換和IO流操作處理教程

    C++類型轉(zhuǎn)換和IO流操作處理教程

    這篇文章主要給大家介紹了關(guān)于C++類型轉(zhuǎn)換和IO流操作處理的相關(guān)資料,標(biāo)準(zhǔn)C++為了加強(qiáng)類型轉(zhuǎn)換的可視性,引入了四種命名的強(qiáng)制類型轉(zhuǎn)換操作符,文中給出了詳細(xì)的代碼示例,需要的朋友可以參考下
    2023-08-08
  • C++實(shí)現(xiàn)基于控制臺(tái)界面的吃豆子游戲

    C++實(shí)現(xiàn)基于控制臺(tái)界面的吃豆子游戲

    這篇文章主要介紹了C++實(shí)現(xiàn)基于控制臺(tái)界面的吃豆子游戲,實(shí)例分析了吃豆子游戲的原理與C++實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-04-04
  • MFC模擬實(shí)現(xiàn)自定義消息發(fā)送

    MFC模擬實(shí)現(xiàn)自定義消息發(fā)送

    在MFC框架下,有很多系統(tǒng)已經(jīng)定義好的消息,例如ON_WM_LBUTTONDOWN()、ON_WM_MBUTTONDOWN()等等。本文將利用這些定義好的消息模擬實(shí)現(xiàn)一下消息發(fā)送,需要的可以參考一下
    2022-01-01

最新評(píng)論

宁蒗| 开化县| 云霄县| 宣城市| 临朐县| 香格里拉县| 广元市| 高邮市| 安福县| 美姑县| 云龙县| 洛隆县| 赤峰市| 郴州市| 曲靖市| 华蓥市| 璧山县| 库车县| 西畴县| 龙里县| 镇雄县| 永德县| 宝丰县| 安吉县| 安义县| 诸暨市| 大埔区| 盐边县| 简阳市| 清丰县| 车致| 宽甸| 明星| 惠来县| 临泉县| 常熟市| 宁晋县| 余江县| 双柏县| 福建省| 新泰市|