for_each (begin(a), end(a), [] (int x) { cout<<x<<" ";});
begin(a)
mang lại một int(*)[3]
(con trỏ đến mảng có kích thước [3]), và dereferencing nó mang lại một int(&)[3]
, trong khi biểu thức lambda của bạn hy vọng một cuộc tranh cãi int
.
for_each (begin(a[0]), end(a[2]), [] (int x) { cout<<x<<" ";});
begin(a[0])
mang lại một int*
trỏ đến phần tử đầu tiên trong hàng đầu tiên của a
, và end(a[2])
mang lại một trỏ int*
đến một quá khứ yếu tố cuối cùng ở hàng cuối cùng của a
, vì vậy mọi thứ hoạt động.
Bây giờ cho phạm vi dựa trên for
.
Nếu bạn xóa &
khỏi dòng for (auto& row : a)
, lỗi thực sự xảy ra trên dòng sau for(auto x : row)
. Điều này là do cách thức range-based for
được chỉ định. Mệnh đề thích hợp với trường hợp sử dụng của bạn là
Nếu __range
là một mảng, sau đó begin_expr được __range
và end_expr là (__range + __bound)
, nơi __bound
là số phần tử trong mảng (nếu mảng có kích thước chưa biết hay là của một loại không đầy đủ, chương trình là vô hình thành)
hereon tôi sẽ đề cập đến định danh được nhắc đến trong Giải thích phần của trang được liên kết.
Hãy xem xét các trường hợp for (auto& row : a)
:
__range
là suy luận như int(&)[3][3]
(tham chiếu đến mảng có kích thước [3] [3]). __begin
sau đó được suy ra dưới dạng int(*)[3]
(trỏ đến mảng có kích thước [3]) vì loại phân đoạn __range
thành con trỏ đến hàng đầu tiên của mảng 2D. range_expression bạn có là auto& row
, vì vậy row
được suy ra là int(&)[3]
(tham chiếu đến mảng kích thước [3]).
Tiếp theo, quá trình tương tự được lặp lại cho phạm vi bên trong dựa trên for
. Trong trường hợp này, __range
là int(&)[3]
và điều khoản mảng tôi trích dẫn ở trên sẽ được áp dụng; quá trình khấu trừ loại còn lại tương tự như những gì tôi đã mô tả ở trên.
__range = int(&)[3]
__begin = int*
x = int
Bây giờ xem xét các trường hợp for (auto row : a)
:
__range
, __begin
và __end
đều suy luận như vậy. Sự khác biệt quan trọng trong trường hợp này là range_expressionauto row
, gây ra sự phân rã của loại int(*)[3]
mà __begin
được suy ra dưới dạng. Điều này có nghĩa là row
được suy ra là int *
và không có mệnh đề nào trong số 3 mệnh đề xác định begin_expr/end_expr được mô tả xử lý con trỏ thô. Điều này dẫn đến lỗi biên dịch trong vòng lặp lồng nhau for
.
Thnx boss! Lời giải thích này rất rõ ràng và ngắn gọn! – Anwesha