Trong một số nơi tôi đã nhìn thấy chữ ký đề nghị của sao chép và di chuyển nhà xây dựng đưa ra như:Một nhà xây dựng di chuyển có tham chiếu const hoặc tham chiếu rvalue không const?
struct T
{
T();
T(const T& other);
T(T&& other);
};
Trường hợp nhà xây dựng bản sao phải mất một tham chiếu const, và các nhà xây dựng chuyển mất một tài liệu tham khảo rvalue không const.
Theo như tôi có thể thấy mặc dù, điều này ngăn cản tôi lợi dụng ngữ nghĩa di chuyển khi trở về đối tượng const từ một chức năng, chẳng hạn như trong trường hợp dưới đây:
T generate_t()
{
const T t;
return t;
}
kiểm tra này với VC11 Beta, T
' s constructor được gọi là, và không phải là nhà xây dựng di chuyển. Ngay cả khi sử dụng return std::move(t);
thì hàm tạo bản sao vẫn được gọi.
Tôi có thể thấy điều này có ý nghĩa như thế nào, vì t
là const nên không được liên kết với T&&
. Sử dụng const T&&
trong chữ ký hàm khởi tạo hoạt động tốt, và có ý nghĩa, nhưng sau đó bạn có vấn đề bởi vì other
là const, bạn không thể null thành viên của nó nếu chúng cần được rỗng - nó sẽ chỉ hoạt động khi tất cả các thành viên là vô hướng hoặc di chuyển các hàm tạo bằng chữ ký đúng. Có vẻ như cách duy nhất để đảm bảo rằng hàm tạo di chuyển được gọi trong trường hợp tổng quát là đã làm cho t
không phải là const ở vị trí đầu tiên, nhưng tôi không thích làm điều đó - những thứ liên kết là hình thức tốt và tôi sẽ không mong đợi khách hàng của T
biết rằng họ phải đi ngược lại biểu mẫu đó để tăng hiệu suất.
Vì vậy, tôi đoán câu hỏi của tôi là gấp đôi; đầu tiên, nên một nhà xây dựng di chuyển mất một const hoặc tham chiếu rvalue không const? Và thứ hai: tôi có đúng trong dòng lý luận này không? Rằng tôi nên ngừng trả lại những thứ là const?
Vâng, tôi nghĩ rằng các trường hợp sử dụng trả về const thời gian là hơi nhỏ. Nếu bạn khai báo trước, thì vì bạn muốn làm một số thứ với nó trước khi trở về. Nếu không, thì một 'return T()' đơn giản sẽ làm. Mặc dù tôi vẫn có thể thấy một số trường hợp sử dụng nhất định, tôi nghĩ chúng hiếm. Và tất nhiên, một tham chiếu rvalue mà từ đó bạn không thể ăn cắp tài nguyên không thực sự có giá trị nào so với một tham chiếu lvalue. Tuy nhiên, câu hỏi đặt câu hỏi. –
Nhân tiện, mã này có đủ điều kiện cho NRVO không? Vì vậy, những gì "nên" xảy ra là đối tượng 'const'' t' được xây dựng vào cùng một vị trí với giá trị trả về không const. Sau đó, nếu cần thiết mà giá trị trả về không const * có thể * được di chuyển bởi người gọi thông qua hàm tạo non-const (hoặc một toán tử gán di chuyển). Tuy nhiên, trong trường hợp xây dựng, nó sẽ lại đủ điều kiện cho phép sao chép bản sao và 't' có thể được xây dựng trực tiếp vào bất kỳ thứ gì đang được khởi tạo bằng cách sử dụng lệnh gọi' generate_t() '. Điều gì cản trở VC11 thực hiện tối ưu hóa này? –
_consting mọi thứ là tốt form_ không nếu bạn muốn sửa đổi chúng, ví dụ: bằng cách di chuyển từ họ. –