自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

C++ push_back()左值和右值的區(qū)別是什么?

開發(fā) 前端
C++11標準對左值和右值做了更細致的劃分:左值 (Lvalue):表示內存中的一個具體位置,可以取地址,通常是一個對象或者變量的引用。右值 (Rvalue):臨時的、不可取地址的對象,通常是表達式的結果。

首先理解下左值和右值。

C++98/03標準中:左值是指有名字的對象,右值是指臨時對象,但是我們提到的時候并不多。

C++11標準對左值和右值做了更細致的劃分:

左值 (Lvalue):表示內存中的一個具體位置,可以取地址,通常是一個對象或者變量的引用。

右值 (Rvalue):臨時的、不可取地址的對象,通常是表達式的結果。

將亡值(xvalue, expiring value):一種特殊的右值,表示將要銷毀的對象(如std::move()返回的對象)

int&& r = std::move(x);  // std::move(x) 是將亡值

純右值(prvalue, pure rvalue):臨時值,表示一個臨時的對象或常量,如字面量、函數(shù)返回值等。

int&& r = 10;       // 10 是純右值(臨時對象)

類左值:類左值是一個統(tǒng)稱,涵蓋了左值(lvalue)和將亡值(xvalue)。它們表示可以引用的對象。類左值包括了所有能夠通過&或&&引用的值,無論是左值還是將亡值。

int x = 10;
int& r = x;  // x 是類左值(glvalue)
int&& r2 = std::move(x);  // std::move(x) 是將亡值(xvalue)

push_back()是std::vector容器的一個成員函數(shù),用來將一個元素添加到容器的末尾?!?/span>

C++11之前,push_back()只有接受const左值引用的版本,所以無論是左值還是右值都會被拷貝到vector中。但C++11引入了移動語義,這時候有了右值引用的重載版本。

如果有std::string str = "hello"; 

然后v.push_back(str),這時候str是左值,會被拷貝。 

而如果是v.push_back(std::move(str)),或者直接push_back("hello"),這時候就是右值,觸發(fā)移動構造,原str的內容被移動到vector中,之后str就空了。

左值傳遞: 

調用push_back(左值)時,會調用拷貝構造函數(shù)。 

#include <iostream>
#include <vector>

class MyClass {
public:
    MyClass(int value) : value(value) {
        std::cout << "MyClass(" << value << ") constructor\n";
    }

    // 拷貝構造函數(shù)
    MyClass(const MyClass& other) : value(other.value) {
        std::cout << "MyClass(" << value << ") copy constructor\n";
    }

private:
    int value;
};

int main() {
    std::vector<MyClass> vec;
    MyClass obj(10);
    // 左值傳遞
    vec.push_back(obj);  // 會調用拷貝構造函數(shù)
    return 0;
}

輸出: 

MyClass(10) constructor
MyClass(10) copy constructor

在這個例子中,當我們將obj(一個左值)傳遞給push_back()時,std::vector需要復制這個對象,調用了MyClass的拷貝構造函數(shù)?!?/span>

右值傳遞: 

調用push_back(右值)時,會調用移動構造函數(shù)。 

容器可以“移動”這個對象到內部,而不需要進行復制。 

這意味著會調用對象的移動構造函數(shù)(如果存在的話),更高效,尤其是當對象比較大或包含大量數(shù)據(jù)時。 

#include <iostream>
#include <vector>

class MyClass {
public:
    MyClass(int value) : value(value) {
        std::cout << "MyClass(" << value << ") constructor\n";
    }

    // 移動構造函數(shù)
    MyClass(MyClass&& other) noexcept : value(other.value) {
        std::cout << "MyClass(" << value << ") move constructor\n";
    }

private:
    int value;
};

int main() {
    std::vector<MyClass> vec;

    // 右值傳遞
    vec.push_back(MyClass(20));  // 會調用移動構造函數(shù)
    return 0;
}

輸出: 

MyClass(20) constructor
MyClass(20) move constructor

在這個例子中,通過MyClass(20)創(chuàng)建了一個臨時對象,這是一個右值。當它傳遞給push_back()時,std::vector會調用移動構造函數(shù),而不是拷貝構造函數(shù)。這樣,MyClass(20)的資源會被“移動”到vec中,而不需要額外的內存分配和復制數(shù)據(jù)?!?/span>

底層實現(xiàn)原理: 

std::vector 的 push_back() 提供兩個重載版本: 

void push_back(const T& val);  // 左值版本:拷貝
void push_back(T&& val);       // 右值版本:移動(C++11 新增)

vector的push_back有兩個重載版本:

一個是const T&,另一個是T&&。

當傳入左值時,編譯器選擇第一個版本,進行拷貝;

當傳入右值時,選擇第二個版本,進行移動?!?/span>

總結: 

特性

左值(push_back(a))

右值(push_back(std::move(a)))

拷貝/移動

拷貝構造

移動構造

原對象狀態(tài)

保留原值

有效但未定義(通常為空)

性能

可能較慢(深拷貝)

通常更快(僅僅轉移資源)

適用對象

需要保留的具名對象

臨時對象或者不再需要的對象

 

責任編輯:武曉燕 來源: CppPlayer
相關推薦

2022-02-16 12:52:22

C++項目編譯器

2025-03-10 08:30:00

2022-03-11 07:59:09

容器代碼元素

2010-02-03 17:32:54

C++左值與右值

2012-02-13 10:18:42

C++ 11

2022-07-26 00:36:06

C#C++函數(shù)

2023-10-23 11:07:37

HTTPRPC

2022-11-15 10:03:34

2021-03-15 14:00:56

PythonC語言編程語言

2016-03-21 10:40:53

RDDSpark SQL數(shù)據(jù)集

2024-12-30 07:20:00

Redis數(shù)據(jù)庫MySQL

2025-02-06 08:44:11

MySQLEXISTSIN

2018-05-21 21:26:59

Apache HiveHbaseSQL

2021-10-27 08:54:11

Pythonencodeencoding

2015-02-26 10:29:41

Google百度

2017-11-21 22:49:10

2022-09-03 08:03:14

UbuntuDebian

2021-02-17 00:30:41

機器學習深度學習人工智能

2012-12-10 09:44:04

路由器本地回路

2022-11-18 16:10:03

云計算虛擬機
點贊
收藏

51CTO技術棧公眾號