1. "Chuyện gì vậy?"
Về std::move()
mặt kỹ thuật là một chức năng - tôi sẽ nói nó không thực sự là một chức năng . Đó là một loại trình chuyển đổi giữa các cách trình biên dịch xem xét giá trị của biểu thức.
2. "Nó làm gì?"
Điều đầu tiên cần lưu ý là std::move()
không thực sự di chuyển bất cứ thứ gì . Nó chuyển đổi một biểu thức từ một giá trị (như một biến được đặt tên) thành một giá trị xvalue . Một xvalue cho trình biên dịch:
Bạn có thể cướp bóc tôi, di chuyển bất cứ thứ gì tôi đang giữ và sử dụng nó ở nơi khác (vì dù sao tôi cũng sẽ bị phá hủy sớm thôi) ".
nói cách khác, khi bạn sử dụng std::move(x)
, bạn đang cho phép trình biên dịch ăn thịt người x
. Do đó, nếu x
có, bộ đệm riêng của nó trong bộ nhớ - sau khi std::move()
ing trình biên dịch có thể có một đối tượng khác sở hữu nó thay thế.
Bạn cũng có thể di chuyển từ một giá trị (chẳng hạn như tạm thời bạn đi ngang qua), nhưng điều này hiếm khi hữu ích.
3. "Khi nào nên sử dụng nó?"
Một cách khác để đặt câu hỏi này là "Tôi sẽ ăn cắp tài nguyên của một đối tượng hiện tại để làm gì?" tốt, nếu bạn đang viết mã ứng dụng, có lẽ bạn sẽ không bị rối tung nhiều với các đối tượng tạm thời được tạo bởi trình biên dịch. Vì vậy, chủ yếu bạn sẽ làm điều này ở những nơi như hàm tạo, phương thức toán tử, hàm giống như thuật toán thư viện chuẩn, v.v ... nơi các đối tượng được tạo và hủy tự động rất nhiều. Tất nhiên, đó chỉ là một quy tắc của ngón tay cái.
Một cách sử dụng thông thường là "di chuyển" tài nguyên từ đối tượng này sang đối tượng khác thay vì sao chép. @Guillaume liên kết đến trang này có một ví dụ ngắn gọn: hoán đổi hai đối tượng với ít sao chép.
template <class T>
swap(T& a, T& b) {
T tmp(a); // we now have two copies of a
a = b; // we now have two copies of b (+ discarded a copy of a)
b = tmp; // we now have two copies of tmp (+ discarded a copy of b)
}
sử dụng di chuyển cho phép bạn trao đổi tài nguyên thay vì sao chép chúng xung quanh:
template <class T>
swap(T& a, T& b) {
T tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
Hãy nghĩ về những gì xảy ra khi T
, nói, vector<int>
có kích thước n. Trong phiên bản đầu tiên, bạn đọc và viết các phần tử 3 * n, trong phiên bản thứ hai, về cơ bản bạn chỉ đọc và viết 3 con trỏ vào bộ đệm của vectơ, cộng với kích thước của 3 bộ đệm. Tất nhiên, lớp T
cần biết làm thế nào để di chuyển; lớp của bạn nên có một toán tử gán chuyển động và một hàm tạo di chuyển cho lớp T
để làm việc này.