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

c/c++中的左值右值詳解

 更新時間:2025年04月08日 09:48:23   作者:Tiantangbujimo7  
這篇文章主要介紹了c/c++中的左值右值,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

左值 (Lvalue)

定義:

  • 表達式結束后依然存在的持久對象。
  • 有名字、有持久性的表達式,它是既能夠出現在等號左邊,也能出現在等號右邊的變量。

右值 (Rvalue)

定義:

  • 表達式結束后就不再存在的臨時對象。
  • 臨時的、將亡的值。一般是不可尋址的常量,或在表達式求值過程中創(chuàng)建的無名臨時對象,短暫性的。

左值和右值主要的區(qū)別之一是左值可以被修改,而右值不能。

int number;
number = 1

在這段代碼中 number 為左值 ,1 為右值。

// getValue()返回的臨時值是右值
int value = getValue();

引用的本質是別名,可以通過引用改變變量的值,傳參時傳引用可以避免拷貝。

左值引用 (Lvalue Reference)

定義: 引用一個對象;

基本用法:

    int number = 10;
    int& count = number;
    count++; // number = count = 11;
  • number 是左值,10 是右值
  • count 是左值引用,count 引用 number
void addCount(int& count)
{
    count++;
}

int number = 10;
addCount(number);

如果給“左值”引用直接賦“右值”,則會報錯,例:

int& number = 10;
報錯:
錯誤 C2440	“初始化”: 無法從“int”轉換為“int &”	

const 左值引用不會修改指向值,因此可以指向右值

例如:

std::vector 中的方法 push_back

// 如果沒有 const 那么使用 v.push_back(10) 這樣 10 的類型是右值,就無法通過編譯了
void push_back(const value_type& _Val)

// 可以直接傳遞字面值
v.push_back(10) 
// 可以傳遞表達式結果
v.push_back(x+y)

右值引用 (Rvalue Reference)

定義:就是必須綁定到右值的引用,它可以指向右值,不能指向左值。C++11中右值引用可以實現“移動語義”,通過 && 獲得右值引用。

右值引用綁定右值

 int&& number = 1;

錯誤:右值引用不能直接綁定左值

    int count = 2;
    int&& number = count;
    報錯:
    error C2440: “初始化”: 無法從“int”轉換為“int &&”
    message : 無法將左值綁定到右值引用

嘗試讓右值引用指向左值

    int count = 2;
    // 使用 std::move 把左值強制轉換為右值 ,number = 2
    int&& number1 = std::move(count);
    // 等同與 std::move 類型轉換 ,number = 2
    int&& number2 = static_cast<int&&>(count);
	// count = number1 = number2 = 10
	number1 = 10;

簡單練習:

void test(int & o) {std::cout << "左值。" << std::endl;}
void test(int && temp) {std::cout << "右值。" << std::endl;}

int main(){
    int a;
	int && b = 10; 

	test(a);
	test(std::move(a));
	test(b);
}
結果:
a 是一個具名變量,有固定的內存地址是典型的左值。輸出:"左值。"
std::move(a) 將左值 a 轉換為右值引用 返回類型是 int&&。輸出:"右值"
雖然 b 的類型是右值引用(int&&)但 b 本身是一個具名變量,可以取地址。 輸出:"左值"

結論:右值引用類型只是用于匹配右值,而并非表示一個右值。因此,盡量不要聲明右值引用類型的變量,而只在函數形參使用它以匹配右值。

淺拷貝(Shallow Copy)

淺拷貝只復制指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存(分支)。

  • 淺拷貝是按位拷貝對象,它會創(chuàng)建一個新對象,這個對象有著原始對象屬性值的一份精確拷貝。
  • 如果屬性是基本類型,拷貝的就是基本類型的值;如果屬性是內存地址(引用類型),拷貝的就是內存地址 ,因此如果其中一個對象改變了這個地址,就會影響到另一個對象。

深拷貝(deep copy)

深拷貝會另外創(chuàng)造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象,是“值”而不是“引用”(不是分支)

  • 拷貝第一層級的對象屬性或數組元素
  • 遞歸拷貝所有層級的對象屬性和數組元素
  • 深拷貝會拷貝所有的屬性,并拷貝屬性指向的動態(tài)分配的內存。當對象和它所引用的對象一起拷貝時即發(fā)生深拷貝。深拷貝相比于淺拷貝速度較慢并且花銷較大。

編寫代碼:

#include <iostream>

class Vector {
    int num;
    int* a;
public:
    // 構造函數
    Vector(int n = 0) : num(n) {
        a = new int[num];
        for (int i = 0; i < num; ++i) {
            a[i] = i + 1;  // 初始化為1,2,3...
        }
    }

    // 析構函數
    ~Vector() {
        delete[] a;
    }

    void ShallowCopy(Vector& v);
    void DeepCopy(Vector& v);

    // 打印數組內容的輔助函數
    void print() const {
        std::cout << "num = " << num << ", array content: ";
        for (int i = 0; i < num; ++i) {
            std::cout << a[i] << " ";
        }
        std::cout << std::endl;
    }

    // 修改數組內容的輔助函數
    void modify(int index, int value) {
        if (index >= 0 && index < num) {
            a[index] = value;
        }
    }
};

// 淺拷貝實現
void Vector::ShallowCopy(Vector& v) {
    this->num = v.num;
    this->a = v.a;
}

// 深拷貝實現
void Vector::DeepCopy(Vector& v) {
    delete[] this->a;  // 先釋放原有內存
    this->num = v.num;
    this->a = new int[num];
    for (int i = 0; i < num; ++i) {
        a[i] = v.a[i];
    }
}

淺拷貝測試

int main() {
    // 測試淺拷貝
    std::cout << "=== 測試淺拷貝 ===" << std::endl;
    {
        Vector v1(5);  // 創(chuàng)建一個包含5個元素的向量
        std::cout << "Original v1: ";
        v1.print();

        Vector v2(3);  // 創(chuàng)建另一個向量
        std::cout << "Original v2: ";
        v2.print();

        v2.ShallowCopy(v1);  // 淺拷貝
        std::cout << "After shallow copy, v2: ";
        v2.print();

        // 修改v1,觀察v2是否變化
        v1.modify(0, 100);
        std::cout << "After modifying v1, v1: ";
        v1.print();
        std::cout << "After modifying v1, v2: ";
        v2.print();

        // 這里會崩潰,因為v1和v2都試圖刪除同一塊內存
        std::cout << "Program will crash here due to double delete\n";
    }
    }
  程序輸出:
  === 測試淺拷貝 ===
Original v1: num = 5, array content: 1 2 3 4 5
Original v2: num = 3, array content: 1 2 3
After shallow copy, v2: num = 5, array content: 1 2 3 4 5
After modifying v1, v1: num = 5, array content: 100 2 3 4 5
After modifying v1, v2: num = 5, array content: 100 2 3 4 5
Program will crash here due to double delete

崩潰位置:
    // 析構函數
    ~Vector() {
        delete[] a;
    }

深拷貝測試

int main() {


    // 測試深拷貝
    std::cout << "\n=== 測試深拷貝 ===" << std::endl;
    {
        Vector v1(5);
        std::cout << "Original v1: ";
        v1.print();

        Vector v2(3);
        std::cout << "Original v2: ";
        v2.print();

        v2.DeepCopy(v1);  // 深拷貝
        std::cout << "After deep copy, v2: ";
        v2.print();

        // 修改v1,觀察v2是否變化
        v1.modify(0, 100);
        std::cout << "After modifying v1, v1: ";
        v1.print();
        std::cout << "After modifying v1, v2: ";
        v2.print();

        // 這里不會崩潰,因為每個對象管理自己的內存
        std::cout << "Program will exit normally\n";
    }

    return 0;
} 

=== 測試深拷貝 ===
Original v1: num = 5, array content: 1 2 3 4 5
Original v2: num = 3, array content: 1 2 3
After deep copy, v2: num = 5, array content: 1 2 3 4 5
After modifying v1, v1: num = 5, array content: 100 2 3 4 5
After modifying v1, v2: num = 5, array content: 1 2 3 4 5
Program will exit normally

再探右值引用

使用 C++ 11 的右值引用,重載拷貝函數,代碼修改為:???????

class Vector {
    int num;
    int* a;
public:
    // 構造函數
    Vector(int n = 0) : num(n) {
        a = new int[num];
        for (int i = 0; i < num; ++i) {
            a[i] = i + 1;  // 初始化為1,2,3...
        }
    }

    // 析構函數
    ~Vector() {
        delete[] a;
    }
    
    //左值引用形參=>匹配左值
    void Copy(Vector& tmp) {

        if (nullptr != this->a){
            delete[] this->a;
        }
      
        this->num = tmp.num;
        this->a = tmp.a;
        
        // 防止tmp析構時刪除內存
        tmp.a = nullptr;    
    }
 
   //右值引用形參=>匹配右值
    void Copy(Vector&& tmp) {
        this->num = tmp.num;
        this->a = tmp.a;
    }
};

調用測試

int main() {
    // 測試左值引用版本
    Vector v1(5);        // v1: {1,2,3,4,5}
    Vector v2;
    v2.Copy(v1);        // 深拷貝:v2獲得自己的內存副本

    // 測試右值引用版本
    Vector v3;
    v3.Copy(Vector(3)); // 移動:直接竊取臨時對象的資源

    return 0;
}

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • C++ 先對數組排序,在進行折半查找

    C++ 先對數組排序,在進行折半查找

    以下小編就為大家介紹兩種實現方法。第一種方法是,選擇排序法+循環(huán)折半查找法。第二種方法是,冒泡排序法+遞歸折半查找法。需要的朋友可以過來參考下,希望對大家有所幫助
    2013-10-10
  • C語言代碼詳細描述順序線性表

    C語言代碼詳細描述順序線性表

    這篇文章主要用代碼介紹了C語言線性表的順序線性表,對于學習數據結構與算法的朋友很有參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • C++中常見容器類的使用方法詳解(vector/deque/map/set)

    C++中常見容器類的使用方法詳解(vector/deque/map/set)

    C++中常見的容器類有vector、list、deque、map、set、unordered_map和unordered_set。下面將舉例直接說明各個容器的使用方法,希望對大家有所幫助
    2023-03-03
  • C語言從基礎到進階全面講解數組

    C語言從基礎到進階全面講解數組

    數組是一組有序的數據的集合,數組中元素類型相同,由數組名和下標唯一地確定,數組中數據不僅數據類型相同,而且在計算機內存里連續(xù)存放,地址編號最低的存儲單元存放數組的起始元素,地址編號最高的存儲單元存放數組的最后一個元素
    2022-05-05
  • 使用C++制作簡單的web服務器(續(xù))

    使用C++制作簡單的web服務器(續(xù))

    本文承接上文《使用C++制作簡單的web服務器》,把web服務器做的功能稍微強大些,主要增加的功能是從文件中讀取網頁并返回給客戶端,而不是把網頁代碼寫死在代碼中,有需要的小伙伴來參考下吧。
    2015-03-03
  • Visual Studio2019調試DLL的實現

    Visual Studio2019調試DLL的實現

    本文主要介紹了Visual Studio2019調試DLL的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-01-01
  • C語言鍵盤控制走迷宮小游戲

    C語言鍵盤控制走迷宮小游戲

    這篇文章主要為大家詳細介紹了C語言鍵盤控制走迷宮小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • 深入剖析Android中init進程實現的C語言源碼

    深入剖析Android中init進程實現的C語言源碼

    這篇文章主要介紹了Android中init進程實現的C語言源碼,init屬性服務在安卓中屬于系統(tǒng)的底層Linux服務,需要的朋友可以參考下
    2015-07-07
  • C++ constexpr的使用小結

    C++ constexpr的使用小結

    constexpr是C++的修飾詞,用于指定編譯期可以求數值的常量表達式,可用于修飾變量,函數,類/結構體,構造函數/析構函數,模板五種情況,下面就來詳細的介紹 一下如何使用
    2026-02-02
  • Visual Studio Code上添加小程序自動補全插件的操作方法

    Visual Studio Code上添加小程序自動補全插件的操作方法

    這篇文章主要介紹了Visual Studio Code上添加小程序自動補全插件的操作方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04

最新評論

天峨县| 桂东县| 德清县| 根河市| 临邑县| 安顺市| 正定县| 尉犁县| 洱源县| 从江县| 昭苏县| 怀来县| 噶尔县| 固始县| 铜鼓县| 东丽区| 重庆市| 南靖县| 台中市| 韩城市| 阿拉善左旗| 九龙坡区| 博白县| 尖扎县| 思南县| 黄山市| 甘泉县| 沙田区| 略阳县| 彰化县| 丰镇市| 平顶山市| 区。| 三门县| 龙口市| 龙山县| 罗甸县| 施秉县| 双流县| 若尔盖县| 平山县|