動機

寫寫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就變這麼複雜了

  1. (想要) cpp想讓複製物件,變成如同複製指標一樣 (躲掉多的deep copy,但是又不想多一個變數去接)
  2. (但是) cpp的語法讓複製資料與複製指標看起來一樣
  3. (所以) 要多一個語法以及傳值作法,處理看起來一樣的傳值
  4. (結果) 我們多了 && 與 move

因為cpp的語法讓複製資料與複製指標看起來一樣,但卻又在使用上把指標與資料區分開來

在其他語言不論物件或是整數的賦值都是起來一樣,但是cpp遇到reference會把一般資料的賦值混在一起,

就變成要再多一個case處理原本的複製資料,最後得到的就是現在的這些東西,還有更複雜的value category

Ref

Java 有值类型吗? What is std::move(), and when should it be used?