2012-02-13 9 views
12

Tôi đã chỉ duyệt qua draft of the C++11 standard và tìm thấy các tuyên bố sau khó hiểu (§13.6/8):unary + trên con trỏ

Đối với tất cả các loại T có tồn tại các chức năng điều hành ứng cử viên có dạng

T* operator+(T*); 

Toán tử "đơn nhất +" này được hiểu như thế nào? Đây có phải chỉ là một sự kiện không bình thường trong trường hợp bình thường, tuy nhiên nó có thể bị quá tải không? Hoặc có một số điểm sâu hơn tôi đang thiếu ở đây?

Trả lời

8

Câu trả lời cho câu hỏi của bạn chỉ là một trang trên các báo giá bạn trích dẫn — §13.6/1:

Các chức năng điều hành ứng cử viên đại diện cho các nhà khai thác tích hợp quy định tại khoản 5 được quy định trong mục này . Các chức năng ứng cử viên này tham gia vào quá trình phân giải quá tải của nhà điều hành như được mô tả trong mục 13.3.1.2 và được sử dụng cho mục đích không khác. [Lưu ý: Vì các toán tử tích hợp chỉ thực hiện các toán hạng với loại không phải lớp và độ phân giải quá tải của toán tử chỉ xảy ra khi biểu thức toán hạng ban đầu có kiểu lớp hoặc kiểu liệt kê, độ phân giải quá tải của nhà điều hành có thể giải quyết toán hạng có kiểu lớp có chuyển đổi do người dùng xác định thành loại không phải lớp thích hợp cho toán tử hoặc khi toán hạng có kiểu liệt kê có thể được chuyển đổi thành loại thích hợp cho toán tử. Cũng lưu ý rằng một số hàm toán tử ứng cử viên được đưa ra trong mục này được cho phép nhiều hơn các toán tử dựng sẵn. Như được mô tả trong 13.3.1.2, sau khi toán tử tích hợp được chọn bằng độ phân giải quá tải, biểu thức phải tuân thủ các yêu cầu đối với toán tử tích hợp được đưa ra trong Điều 5, và do đó có thêm bất kỳ hạn chế ngữ nghĩa nào. Nếu có một ứng cử viên được viết với cùng tên và các kiểu tham số như một hàm toán tử ứng viên dựng sẵn, hàm toán tử dựng sẵn được ẩn và không được bao gồm trong tập các hàm ứng cử viên. -end lưu ý]

+0

Vậy toán tử 'T * + (T *);' là thành viên hay toàn cục? và trong trường hợp của lambda -> '+ [] {};' cái gì là 'T' tôi tự hỏi? Cảm ơn –

+0

@AngelusMortis: Con trỏ không thể có thành viên; điều này sử dụng hàm dựng sẵn đơn nhất của ngôn ngữ được gọi là 'operator +' cho các kiểu số học.Và kiểu '+ [] {}' là 'void (*)()', như là toán tử 'đơn nhất +' trên các lambdas vô hình chuyển đổi lambda thành một con trỏ hàm. – ildjarn

+0

Thưa ông, tôi vẫn còn chút bối rối, vì vậy hãy hỏi bằng cách trích dẫn câu của bạn -> "Con trỏ không thể có thành viên" có nhưng tôi đã nghĩ ban đầu lambdas được chuyển đổi thành loại lớp (bởi trình biên dịch) quá tải 'operator()', do đó Tôi nghĩ họ có thể là thành viên. Bây giờ câu lệnh của bạn "điều này sử dụng toán tử nội trú đơn nhất' của ngôn ngữ + cho các kiểu số học ", tôi chắc chắn các kiểu số học về cơ bản là các kiểu float + float, sau đó cách biểu thức ->' + []() '->' operator + (some_unknown_type_I_don) 't_know) '-> được chuyển thành' void (*)() ' –

0

Vâng, bạn có thể quá tải nó làm bất cứ điều gì bạn muốn, nhưng nó chỉ có đối xứng với toán tử đơn nhất. Như bạn đề cập, nó chỉ là một không-op hầu hết thời gian.

+3

có thể không? _operator phải có một đối số của lớp hoặc liệt kê type_? – Lol4t0

8

Các + trên con trỏ là một noop trừ biến điều cần rvalues. đôi khi nó là thuận tiện nếu bạn muốn phân rã mảng hoặc chức năng

int a[] = { 1, 2, 3 }; 
auto &&x = +a; 

Bây giờ x là một int*&& và không phải là một int(&)[3]. Nếu bạn muốn vượt qua x hoặc +a cho các mẫu, sự khác biệt này có thể trở nên quan trọng. a + 0 không phải lúc nào cũng tương đương, hãy xem xét

struct forward_decl; 
extern forward_decl a[]; 
auto &&x = +a; // well-formed 
auto &&y = a + 0; // ill-formed 

Dòng cuối cùng là vô hình thành, bởi vì thêm bất cứ điều gì để một con trỏ đòi hỏi của con trỏ chỉ đến kiểu lớp được định nghĩa hoàn toàn (vì nó tiến bởi sizeof(forward_decl) * N byte).

+0

không phải là những gì 'std :: move()' và 'std :: forward()' có nghĩa là để làm gì? Vì vậy, nếu tôi hiểu điều này một cách chính xác '+ a' và 'std :: move (a)' sẽ làm tương tự? – LiKao

+1

@LiKao không có gì cả. 'move' giữ nguyên kiểu, nhưng chỉ thay đổi loại giá trị. Vì vậy,' move (a) 'sẽ tạo ra một rvalue của gõ 'int [3]', không phải là rvalue của kiểu 'int *'. Bây giờ việc áp dụng 'move' vào một hàm không làm gì cả (đúc thành' FunctionType && 'yields lvalue) và không có ý nghĩa đặc biệt –

+0

@LiKao: Không, 'std :: move' giữ nguyên mảng, trong khi unary + phân rã nó (và tạo ra một con trỏ rvalue) – Xeo