c++對象所有權(quán)的手記-創(chuàng)新互聯(lián)

1.先理解下c++為什么會需要move?

---- 變量,所有權(quán),以及性能優(yōu)化。

我們提供的服務有:成都網(wǎng)站制作、成都做網(wǎng)站、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認證、青銅峽ssl等。為上1000家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務,是有科學管理、有技術(shù)的青銅峽網(wǎng)站制作公司2.變量

從實用的角度,變量可以分為兩類:

  1. 沒有指針或引用的變量,可以稱為trivial type。? (c++11,平凡可復制的概念用的也是trivial這個詞)
  2. 有指針或引用的變量,可以稱handle type。

簡化理解,trivial type數(shù)據(jù),沒有指針、引用直接放在棧上的,無須優(yōu)化性能。

而handle type通常有兩部分數(shù)據(jù):第一部分可以放在棧上,第二部分在堆里

棧上的數(shù)據(jù)——就叫做handle,用來控制(handle)堆上的數(shù)據(jù)。從這個角度看棧上的數(shù)據(jù)是堆數(shù)據(jù)的所有者(owner) )。

c++ 語法move一般針對的是handle type的變量。

為什么Python,JavaScript,Java等等都沒有move這個概念呢?

因為在這些有GC的語言里面,它們處理handle type的時候,賦值既具有"move"的性質(zhì),又具有copy的性質(zhì)——實際是將引用復制給另外一個變量。

比如下面JavaScript代碼

let a = { name: "good"};
let b = a;
b.name = "Bad";
// a,b的名字都變成了bad.

這里變量b與a引用著同樣的對象,它們就是一個引用而已。

b = a就是將這個名字給了b變量,它們指代的是同一個東西。

當我們通過b修改數(shù)據(jù),此時a引用著的對象自然而然就已經(jīng)修改了。

顯然,此時無所謂move動作,因為b跟a指代同樣的對象,這是很直觀的想法。

更準確的說法是copy 棧上的名字,根本沒有發(fā)生任何所有權(quán)的轉(zhuǎn)移概念。

我們看下 C++里面,類似的b = a,默認的是拷貝復制,而不是引用。

void test()
{
	auto a = vector{ "str1", "str2", "str3" };
		auto b = a;
		b[0] = "b string";
		for (auto v : a) {
			cout<< v<< ", ";
		}
		cout<< endl;
		for (auto v : b) {
			cout<< v<< ", ";
		}
		cout<< endl;
}

輸出:

str1, str2, str3,
b string, str2, str3,

對比js的引用a、b,都在棧上,天然的指向同一個堆空間,只是別名。

而c++的變量a、b,都在棧上,指向了不同的堆空間,b=a,是復制了一份給到b指向的空間。

(像java,JS等有GC的語言為了更好地管理內(nèi)存,基本不做堆棧的區(qū)分——不用關(guān)心是在棧上還是堆里。GC幫忙管理著內(nèi)存,這是這些語言沒有move概念的原因)

上面JS例子只拷貝了棧上面的引用(它們無須操作堆復制),而C++既拷貝了棧那部分數(shù)據(jù)也拷貝了堆里面的內(nèi)容

如果,c++想實現(xiàn)所有權(quán)的轉(zhuǎn)換呢,因此,C++11 引入了move的概念,我們只拷貝棧上的數(shù)據(jù)的時候,并引用到已有的堆數(shù)據(jù)(不另外分配堆內(nèi)存并拷貝堆數(shù)據(jù),提高性能)。

3.value categories也做了調(diào)整,從而規(guī)定哪些value可以被move

(左值、右值、將亡值)

  1. prvalue - 純右值 。就是用于計算的或者用于初始化對象的。(pure)
  2. xvalue?-? 將亡值。就是臨時變量。它是快要被銷毀的值。(expiring)
  3. lvalue -? 左值。在內(nèi)存中具有位置的值。所有具名變量都是左值 (left)

xvalue可以被直接move。

prvalue被move的時候,可以理解生成了一個臨時變量xvalue,并move了這個臨時變量。

lvalue,則需要使用std::move將lvalue變成xvalue,并move了這個xvalue。

4.c++中的move

??? ?std::string a = "stringaaa";
??? ?auto b = std::move(a);
??? ?cout<< b<< endl;
原來變量a指代的值的所有權(quán)轉(zhuǎn)移給了b,變量a被置成“空”了

move的場景例子。

  1. 接管資源
void My::take(Book && iBook) 
{
  mBook = std::move(iBook); //將沒人要的iBook,拿過來據(jù)為己有
}

2. 轉(zhuǎn)移所有權(quán)

auto thread = std::thread([]{});
std::vectorlThreadPool;
lThreadPool.push_back(std::move(thread)); //現(xiàn)在thread pool來掌控著thread

3. 避免拷貝

void f() {
  std::vector v = ...;
  take(std::move(v)); // 直接move進了函數(shù)g里面,不用拷貝
}

move是轉(zhuǎn)移對象的所有權(quán),所以我們可以move的是可以轉(zhuǎn)移所有權(quán)的對象。

可以移動右值,也可以把左值通過std::move變成右值,從而可以實現(xiàn)移動。

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

當前文章:c++對象所有權(quán)的手記-創(chuàng)新互聯(lián)
標題來源:http://bm7419.com/article34/didese.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供服務器托管、軟件開發(fā)、App開發(fā)、網(wǎng)站設計公司品牌網(wǎng)站設計、定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設