2011-08-21 11 views
7

Một số thời gian trước đây tôi đã được nói, rằng mô hình thông thường để thực hiện hai nhà khai thác một nhu cầu cuối cùng move trong sự trở lại.Toán tử C++ 0x T + (const T &, T &&), vẫn cần di chuyển?

Matrix operator+(const Matrix &a, Matrix &&b) { 
    b += a; 
    return std::move(b); 
} 

Nhưng bây giờ có quy tắc đặc biệt mà trong một return trình biên dịch có thể đối xử với giá trị trả về là một tạm thời, và sau đó điều này sẽ không cần thiết - một đơn giản return b sẽ đủ.

Nhưng sau đó một lần nữa, btên trong chức năng này, do đó, một vế trái của nó - mà gây cản trở các trình biên dịch để m xem xét nó là một temp, và move là bắt buộc.

Đây có phải là trường hợp trong phiên bản gần đây nhất của tiêu chuẩn C++ 0x không? Chúng tôi cần move để triển khai mẫu trên?

+2

Theo [câu trả lời này] (http://stackoverflow.com/questions/6009004/are-value-parameters-implicitly-moved-when -trả lại-by-value/6009012 # 6009012), 'std :: move' là không cần thiết. – fredoverflow

+2

Mặc dù nó có thể tạo sự khác biệt rằng tham số là một 'Ma trận &' thay vì một 'Ma trận' ... – fredoverflow

+2

Nó * là * phức tạp, vâng. Và vâng, tôi nghĩ bạn đúng. Nếu tham số giá trị * của nó * giống như 'Ma trận' thì bạn có một bản sao nguyên sơ cho riêng bạn - một tạm thời. Trình biên dịch biết rằng bạn có thể lấy từ nó. Với 'Ma trận & 'Tôi không * rằng * chắc chắn- – towi

Trả lời

7

Bạn cần rõ ràng std::move trong ví dụ này vì b không phải là tên của một đối tượng non-volatile tự động. Tham khảo 12,8 [class.copy]/P31/b1:

  • trong một tuyên bố trở lại trong một hàm với một kiểu lớp trở lại, khi biểu thức là tên của một đối tượng non-volatile tự động (tham số khác hơn một chức năng hoặc bắt-khoản) với cùng CV- loại không đủ tiêu chuẩn như các loại chức năng Đổi lại, các hoạt động sao chép/di chuyển thể được bỏ qua bằng cách xây dựng các đối tượng tự động trực tiếp vào giá trị trả về các chức năng của
+2

Ah, và tham chiếu không phải là đối tượng. Tôi nghĩ bạn nên nhấn mạnh "đối tượng" thay vì "tự động" (hoặc cả hai). – fredoverflow

+0

Tôi nghĩ rằng ** tự động ** là đúng ở đây, vì nó dịch (gần đúng? Chính xác?) Thành "biến cục bộ". – towi

0

Tôi không chắc tại sao hàm này trả về giá trị. Không nên chức năng này trả lại Matrix&& như sau?

Matrix&& operator+(const Matrix &a, Matrix &&b) { 
    b += a; 
    return std::move(b); 
} 

này có lợi thế thêm rằng x1 + x2 + x3 + ... + xn tạo ra nhiều nhất là một tạm thời, đó là quan trọng nếu Matrix xảy ra để được stack giao (vì nó sau đó giành gì từ động thái).

Tôi nghĩ rằng chữ ký nên như sau:

Matrix&& operator+(Matrix &&a,  Matrix &&b ); 
Matrix&& operator+(const Matrix &a, Matrix &&b ); 
Matrix&& operator+(Matrix &&a,  const Matrix &b); 
Matrix operator+(const Matrix &a, const Matrix &b); 
+0

Không. Bạn không nên trả về '&&'. Điều này có nghĩa là, bạn trả lại một tham chiếu đến một trong các đối số, nơi bạn không có quyền kiểm soát nơi nó đến từ đâu ("không nhặt những gì nằm trên đường phố").Nếu bạn trả về một 'ma trận', bạn chỉ có thể 'di chuyển' trong nội dung từ một trong các đối số và bạn hoàn thành hiệu ứng tương tự với hiệu năng hoàn hảo. Ngoài ra, bạn không cần phải quá tải trên '(&&, &&)': Mã bạn sẽ viết ở đó sẽ giống như trong '(&, &&)' hoặc '(&&, &&)'. Nếu bạn bỏ quá tải '(&&, &&)', một trong số đó sẽ được trình biên dịch lựa chọn. Bạn chỉ cần 3 quá tải. – towi

+0

towi: Có gì sai khi trả lại tham chiếu đến một trong các đối số? Tôi nghĩ chỉ trả lại một tham chiếu đến tạm thời là một vấn đề. – Clinton

+1

@towi: Ngoài ra, bạn có chứng cớ gì về tình trạng quá tải '(&&, &&)' là không cần thiết? Tôi tin rằng http://ideone.com/qf3Rn cho thấy rằng nó là cần thiết. – Clinton