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資料成員都可以移動時,編譯器才會為其合成移動建構函式或移動賦值運算子。
structx;struct
hasx;
x x,x2=std::move(x);//
使用合成移動建構函式
hasx hx,hx2=std::move(hx); //
使用合成移動建構函式
5.4 定義了乙個移動建構函式或移動賦值運算子的類,必須定義自己的拷貝操作。否則,這些成員將是delete的
6.移動右值,拷貝左值。但若沒有移動建構函式,右值也被拷貝。
7.乙個類有乙個可用的拷貝建構函式,沒有移動建構函式,則物件是通過拷貝建構函式來「移動」的。同理,適用於拷貝賦值運算子和移動賦值運算子。
classstrvec
//預設初始化
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 右值引用如何修飾成員函式,什麼含義,怎麼呼叫
classfoo
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 中,乙個變數是左值還是...