2012-03-17 62 views
14

Câu hỏi này xuất phát từ các vấn đề được nêu ra bởi this answer.Việc đánh số các toán tử gán với các giá trị thay vì tham chiếu

Thông thường, chúng tôi xác định toán tử gán bản sao cho loại TT& operator=(const T&) và di chuyển toán tử gán cho loại TT& operator=(T&&).

Tuy nhiên, điều gì xảy ra khi chúng tôi sử dụng tham số giá trị thay vì tham chiếu?

class T 
{ 
public: 
    T& operator=(T t); 
}; 

Điều này sẽ giúp T vừa sao chép vừa di chuyển được. Tuy nhiên, những gì tôi muốn biết là phân nhánh ngôn ngữ cho T là gì?

Cụ thể:

  1. Liệu đếm này như một toán tử gán bản sao cho T, theo các đặc điểm kỹ thuật?
  2. Điều này có được tính là toán tử chuyển nhượng di chuyển cho T, theo đặc điểm kỹ thuật không?
  3. Liệu T có toán tử gán bản sao do trình biên dịch tạo không?
  4. Liệu T có toán tử gán di chuyển do trình biên dịch tạo không?
  5. Điều này ảnh hưởng như thế nào đến các lớp học đặc điểm như std::is_move_assignable?
+0

Thảo luận liên quan: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value – mavam

+0

Tôi gặp lỗi trình biên dịch trên cả Visual Studio và g ++ nếu tôi có thứ gì đó cả T & operator = (T t) và T & operator = (T && t) vì nó mơ hồ – user929404

+0

@ user929404: Và bạn nên làm như vậy. Vấn đề là bạn thay thế * cả * bản sao và chuyển nhượng nhiệm vụ chỉ với gán giá trị. –

Trả lời

14

Hầu hết điều này được mô tả trong §12.8. Đoạn 17 định nghĩa những gì đếm như toán tử gán bản sao sử dụng tuyên bố:

Một người sử dụng-công bố bản phân công điều hành X::operator= là một tổ chức phi mẫu hàm thành viên không tĩnh của lớp X với chính xác một tham số có kiểu X, X&, const X&, volatile X& hoặc const volatile X&.

Đoạn 19 định nghĩa những gì đếm như toán tử gán di chuyển người dùng tuyên bố:

Một người dùng tuyên bố động thái nhượng nhà điều hành X::operator= là một tổ chức phi tĩnh phi mẫu hàm thành viên của lớp X với chính xác một thông số của loại X&&, const X&&, volatile X&& hoặc const volatile X&&.

Vì vậy, nó được tính là toán tử gán bản sao, nhưng không phải là toán tử gán nhiệm vụ.

Đoạn 18 nói khi trình biên dịch tạo ra bản sao toán tử gán:

Nếu định nghĩa lớp không tuyên bố một cách rõ ràng một bản sao phân điều hành, người ta được khai báo ngầm. Nếu định nghĩa lớp khai báo một hàm tạo di chuyển hoặc toán tử gán di chuyển, thì rõ ràng toán tử gán bản sao đã khai báo được định nghĩa là đã xóa; nếu không, nó được định nghĩa là mặc định (8.4).Trường hợp thứ hai không được chấp nhận nếu lớp có một hàm tạo bản sao do người dùng khai báo hoặc một khai báo hủy người dùng do người dùng khai báo.

Đoạn 20 cho chúng ta biết khi trình biên dịch tạo ra di chuyển các toán tử gán:

Nếu định nghĩa của một lớp X không tuyên bố một cách rõ ràng một toán tử gán di chuyển , ai sẽ được khai báo ngầm như mặc định nếu và chỉ khi
[...]
- X không có một toán tử gán bản sao do người dùng khai báo,
[...]

Vì lớp này có một toán tử gán bản sao do người dùng khai báo, nên không có trình biên dịch ngầm nào được tạo ra bởi trình biên dịch.

std::is_copy_assignablestd::is_move_assignable được mô tả trong bảng 49 có cùng giá trị tương ứng là is_assignable<T&,T const&>::valueis_assignable<T&,T&&>::value. bảng cho chúng ta biết rằng is_assignable<T,U>::valuetrue khi:

Khái niệm declval<T>() = declval<U>() là tốt được hình thành khi điều trị như một toán hạng unevaluated (khoản 5). Kiểm tra quyền truy cập được thực hiện dưới dạng nếu trong ngữ cảnh không liên quan đến TU. Chỉ có hiệu lực của ngữ cảnh ngay lập tức của biểu thức gán được xem xét.

Vì cả hai declval<T&>() = declval<T const&>()declval<T&>() = declval<T&&>() đều được thiết lập tốt cho lớp đó, nó vẫn được tính là có thể gán và chuyển nhượng được.

Như tôi đã đề cập trong phần nhận xét, điều quan trọng là, với sự hiện diện của một hàm tạo di chuyển, operator= sẽ thực hiện đúng các bước di chuyển, nhưng về mặt kỹ thuật không được tính là toán tử gán di chuyển. Nó thậm chí còn xa lạ hơn nếu lớp không có hàm tạo bản sao: nó sẽ có một toán tử gán bản sao không sao chép, nhưng chỉ di chuyển.

Các vấn đề liên quan