動機
寫寫std::move的筆記
value type & reference type
- value type: 每個變數持有的都是獨立的資料
- reference type: 每個變數持有的都是地址
所以如果使用者想感受到value type就要看到,
對變數修改時其他變數看的到
pointer in C & reference in CPP
cpp 預設的傳值是pass-by-value,所以會copy的是資料,而(Java, Python…)大部分的PL傳的都是reference
就因為cpp的這件事,變成他與c一樣都要把指標丟來丟去,而cpp不想寫星號(悲劇的開始),所以加了pass-by-reference
回到c來看,會有指標的是變數(已經被賦值的),只能從變數取指標(如果要直接指定記憶體位置,c是做得到啦,但這邊不談這個)
但如果是像
int *a = 1+2;
int &b = 1+2;
就會出事,因為資料沒有被變數接住,就不能被指定到指標與參考,這十分不方便
例子
int add(int &a, int &b)
return a+b;
}
add(1+2,1+2);
遇到這種,就要先把資料assign到變數後才能用
std::move
所以cpp這次怎麼曲線救國?
再多一個傳值的選項,說
我之後就用不到了,可以把我搬空(rvalue, xvalue) ? 而std::move就是把一個變數轉成說可以搬空我這樣
整體std::move大概像
static_cast<typename std::remove_reference<T>::type&&>(t)
搬空?
見下面的例子
class string {
char* data
public:
string (const char* p) {
size_t size = std::strlen(p) + 1;
data = new char[size];
std::memcpy(data, p, size);
}
string (string&& rhs) {
data = rhs.data;
rhs.data = nullptr; // 搬空
}
~string() {
delete[] data;
}
};
頭好昏,在c好好的,怎麼到cpp就變這麼複雜了
- (想要) cpp想讓複製物件,變成如同複製指標一樣 (躲掉多的deep copy,但是又不想多一個變數去接)
- (但是) cpp的語法讓複製資料與複製指標看起來一樣
- (所以) 要多一個語法以及傳值作法,處理看起來一樣的傳值
- (結果) 我們多了
&&
與 move
因為cpp的語法讓複製資料與複製指標看起來一樣,但卻又在使用上把指標與資料區分開來
在其他語言不論物件或是整數的賦值都是起來一樣,但是cpp遇到reference會把一般資料的賦值混在一起,
就變成要再多一個case處理原本的複製資料,最後得到的就是現在的這些東西,還有更複雜的value category
Ref
Java 有值类型吗? What is std::move(), and when should it be used?