C 右值引用

2022-07-29 01:27:13 字數 3540 閱讀 5370

1.繫結到乙個將要銷毀的右值的引用——移動

2.左值表示式——物件的身份;右值表示式——物件的值

int i=42

;int& r=i;

int&& rr=i;//

×,左值不能繫結到右值引用

int& r2=i*42;//

×,右值不能繫結到左值引用

const

int& r3=i*42;//

√,右值可以繫結const引用

int&& rr2 = i*42;//

右值繫結到右值引用

int&& rr1=42;//

√int&& rr2=rr1;//

×int&& rr3=std::move(rr1);//√,使用std可以避免潛在的命名衝突

3.左值持久,右值短暫(一般是字面常量,或表示式建立的臨時物件(如上))//變數壽命很長的,出}才會被銷毀

4.右值引用的物件即將被銷毀且該物件沒有其他使用者

5.移動建構函式和移動賦值運算子

5.1 移動建構函式不分配任何新記憶體,直接接管給定的記憶體,接管後將原物件置為null

strvec(strvec&& s) noexcept :elements(s.elements), first_free(s.first_free), cap(s.cap)//

接管s的資源

5.2 移動賦值運算子

strvec& operator=(strvec&&rhs) noexcept//為何其他地方不需要?

return *this

; }

5.3 合成移動操作:

類定義了自己的拷貝建構函式、拷貝賦值運算子或析構函式,便不會合成移動建構函式和移動賦值運算子。只有當乙個類未定義任何自己版本的拷貝控制成員,且類的每個非static資料成員都可以移動時,編譯器才會為其合成移動建構函式或移動賦值運算子。

struct

x;struct

hasx;

x x,x2=std::move(x);//

使用合成移動建構函式

hasx hx,hx2=std::move(hx); //

使用合成移動建構函式

5.4 定義了乙個移動建構函式或移動賦值運算子的類,必須定義自己的拷貝操作。否則,這些成員將是delete的

6.移動右值,拷貝左值。但若沒有移動建構函式,右值也被拷貝。

7.乙個類有乙個可用的拷貝建構函式,沒有移動建構函式,則物件是通過拷貝建構函式來「移動」的。同理,適用於拷貝賦值運算子和移動賦值運算子。

class

strvec

//預設初始化

strvec(const strvec&);//

拷貝構造

strvec& operator=(const strvec&);//

拷貝賦值運算子

~strvec();

strvec(strvec&& s) noexcept :elements(s.elements), first_free(s.first_free), cap(s.cap)//

接管s的資源

strvec& operator=(strvec&&rhs) noexcept

return *this

; }

void push_back(const

string&);//

拷貝元素

void push_back(string&&);//

移動元素,右值引用

string* begin() const

string* end() const

size_t size()

const

size_t capacity()

const

private

:

static std::allocatorstring> alloc;//

分配器void chk_n_alloc() //

每一次新增元素都要check

pair

alloc_n_copy(const

string*, const

string*);//

工具,給拷貝構造、賦值運算子和析構用

void reallocate(); //

獲得更多記憶體並拷貝元素

void

free(); //

銷毀釋放記憶體

std::

string *elements; //

指向陣列元素的指標

std::string *first_free; //

指向第乙個空閒元素的指標

std::string *cap; //

指向陣列尾後位置的指標

};void strvec::push_back(const

string&s)

void strvec::push_back(string&&s)

strvec vec;

string s = "some thing";

vec.push_back(s);//呼叫push_back(const string& s)

vec.push_back("done");//呼叫push_back(string&& s)

8.左值和右值的引用成員函式

8.1 右值引用如何修飾成員函式,什麼含義,怎麼呼叫

class

foo

foo sorted() &&;

foo sorted()

const &;

private

: list

data;

};foo foo::sorted() &&//本物件是右值,沒有其他使用者,可以對源物件排序

foo foo::sorted()

const &//本物件是左值,只能先複製乙份,再排序,不能改變原來的

8.2 定義兩個或以上同名同引數列表的成員函式,要麼都加上引用限定符,要麼都不加

foo sorted() && ;//

1 foo sorted() const &;//

2都加(如果沒有&就×)

using comp = bool(const

int&, const

int&);//

com是函式型別的型別別名

foo sorted(comp*);//

3 foo sorted(comp*) const;//

4都不加(如果有&就×)

9.問題

virtual quote* clone() && 

virtual shared_ptrclone() const &

有了&&限定符,*this本身就是右值?為何還要std::move(*this)呢?不能return new quote(*this)?這種函式什麼時候用?

c 左值 右值 右值引用 左值引用

c 裡一切值必須屬於左值 右值兩者之一。左值 一切變數 包括用const修飾的變數 物件 包括引用都屬於左值 右值 一切字面值 可以是巨集 臨時無名物件 函式返回值 表示式 如a n 說明一下 函式返回值,返回的是某乙個型別的值,並不是返回變數。左值並不是說能放在 左邊的值就是左值 雖然用const...

c 左值 右值 左值引用 右值引用

在c語言中,左值認為是賦值語句的左側,右值認為是賦值語句的右側。在c 中,意義稍有不同。c 中,每乙個表示式會產生乙個左值或者右值,相應的,該表示式也就被稱作 左值表示式 右值表示式 乙個左值表示式的求值結果是乙個物件或者是乙個函式。左值可以當右值使用,而右值不能當左值使用。c prime 中這麼簡...

C 左值 右值 左值引用 右值引用

就變數而言,對於一些變數,我們只會讀取並使用它們的值,而不會改變他們的值 唯讀 對於其餘的變數,我們既會讀取它們的值,有的時候還會改變它們的值 讀寫 這是很常見的。在c 中,前一種變數稱為右值,後一種變數稱為左值,例如 int a 1 a是左值,1是右值稍稍不同的一點是,在c 中,乙個變數是左值還是...