Truyền một mảng bằng cách tham chiếu


184

Làm thế nào để vượt qua một mảng được phân bổ tĩnh bởi công việc tham chiếu?

void foo(int (&myArray)[100])
{
}

int main()
{
    int a[100];
    foo(a);
}

(&myArray)[100]bất kỳ ý nghĩa hoặc nó chỉ là một cú pháp để vượt qua bất kỳ mảng bằng tham chiếu? Tôi không hiểu dấu ngoặc đơn riêng biệt theo sau bởi dấu ngoặc lớn ở đây. Cảm ơn.


Có bất kỳ mối quan hệ Rvalue đến Lvalue với các tham số chức năng?
John DB


Câu trả lời:


228

Đó là một cú pháp cho tham chiếu mảng - bạn cần sử dụng (&array)để làm rõ cho trình biên dịch rằng bạn muốn tham chiếu đến một mảng, thay vì mảng tham chiếu (không hợp lệ) int & array[100];.

EDIT: Một số làm rõ.

void foo(int * x);
void foo(int x[100]);
void foo(int x[]);

Ba cách này là các cách khác nhau để khai báo cùng một chức năng. Tất cả đều được coi là lấy một int *tham số, bạn có thể chuyển bất kỳ mảng kích thước nào cho chúng.

void foo(int (&x)[100]);

Điều này chỉ chấp nhận mảng 100 số nguyên. Bạn có thể sử dụng một cách an toàn sizeoftrênx

void foo(int & x[100]); // error

Điều này được phân tích cú pháp như là một "mảng tham chiếu" - không hợp pháp.


Tại sao chúng ta không thể có một loạt các tài liệu tham khảo, ví dụ int a, b, c; int arr[3] = {a, b, c};?
Vorac

4
Aha, tìm ra lý do tại sao .
Vorac

2
Ai đó có thể giải thích tại sao void foo(int & x[100]);được phân tích cú pháp là "mảng tài liệu tham khảo" không? Có phải vì quy tắc "từ phải sang trái"? Nếu có, nó dường như không phù hợp với cách void foo(int (&x)[100]);phân tích cú pháp là "tham chiếu đến một mảng". Cảm ơn trước.
zl9394

3
Nó không phải từ trái sang phải, nó từ trong ra ngoài và [] liên kết chặt chẽ hơn &.
philipxy

48

Đó chỉ là cú pháp cần thiết:

void Func(int (&myArray)[100])

^ Truyền mảng 100 intbằng cách tham chiếu tên tham số là myArray;

void Func(int* myArray)

^ Vượt qua một mảng. Mảng phân rã thành một con trỏ. Do đó bạn mất thông tin kích thước.

void Func(int (*myFunc)(double))

^ Truyền một con trỏ hàm. Hàm trả về một intvà mất một double. Tên tham số là myFunc.


Làm thế nào để chúng ta vượt qua một mảng kích thước thay đổi như một tài liệu tham khảo?
Shivam Arora

@ShivamArora Bạn khuôn mẫu hóa chức năng và biến kích thước thành tham số mẫu.
Martin York

24

Đây là một cú pháp. Trong các đối số hàm int (&myArray)[100]ngoặc đơn kèm theo &myArraylà cần thiết. nếu bạn không sử dụng chúng, bạn sẽ vượt qua array of referencesvà đó là vì subscript operator []ưu tiên cao hơn so với & operator.

Ví dụ int &myArray[100] // array of references

Vì vậy, bằng cách sử dụng, type construction ()bạn nói với trình biên dịch rằng bạn muốn tham chiếu đến một mảng gồm 100 số nguyên.

Ví dụ int (&myArray)[100] // reference of an array of 100 ints


"Nếu bạn không sử dụng chúng, bạn sẽ vượt qua array of references" - tất nhiên, không thể tồn tại, do đó bạn sẽ gặp lỗi biên dịch. Điều thú vị với tôi là các quy tắc ưu tiên toán tử khẳng định điều này phải xảy ra theo mặc định.
gạch dưới

Có hướng dẫn nào thêm về kiểu xây dựng () không?
Shifter trưởng

Cảm ơn, tôi cần một lời giải thích bao gồm lý do về quyền ưu tiên của nhà điều hành, điều này mang lại ý nghĩa cho lý do tại sao nó nên được thực hiện theo cách này.
cram2208

4

Mảng được mặc định thông qua con trỏ. Bạn có thể thử sửa đổi một mảng bên trong một lời gọi hàm để hiểu rõ hơn.


2
Mảng không thể được thông qua bởi giá trị. Nếu hàm nhận được một con trỏ, một mảng sẽ phân rã thành một con trỏ tới phần tử đầu tiên của nó. Tôi không chắc những gì bạn đang cố gắng nói ở đây.
Ulrich Eckhardt

@UlrichEckhardt Tôi đang cố gắng nói rằng "Mảng không thể được thông qua giá trị" như bạn đã nói trước đây, chúng được mặc định thông qua tham chiếu
Eduardo A. Fernández Díaz

8
Mảng không được truyền bởi giá trị cũng như tham chiếu. Chúng được thông qua bởi con trỏ. Nếu các mảng được truyền theo tham chiếu theo mặc định, bạn sẽ không gặp vấn đề gì khi sử dụng sizeof trên chúng. Nhưng đó không phải là trường hợp. Mảng phân rã thành con trỏ khi truyền vào hàm.
dùng3437460

2
Mảng có thể được truyền bằng tham chiếu HOẶC bằng cách khử xuống một con trỏ. Ví dụ, bằng cách sử dụng char arr[1]; foo(char arr[])., mảng xuống cấp cho một con trỏ; trong khi sử dụng char arr[1]; foo(char (&arr)[1]), mảng được truyền dưới dạng tham chiếu. Đáng chú ý là hình thức trước đây thường được coi là không định hình do kích thước bị mất.
zl9394

Re, "Mảng được ... thông qua con trỏ." Mô tả đó nghe có vẻ độc đáo nhất, và nó có thể gây nhầm lẫn cho người mới. Các tên của một biến mảng, là một biểu thức hợp lệ có giá trị là một con trỏ những thành viên đầu tiên của mảng. Nếu bạn có một số hàm foo(T* t)và bạn có một mảng T a[N];thì khi bạn viết foo(a);tôi nghĩ sẽ đúng hơn khi nói rằng bạn đang truyền một con trỏ, không truyền một mảng và bạn đang truyền con trỏ theo giá trị.
Solomon chậm

1

Sau đây tạo ra một hàm chung, lấy một mảng có kích thước bất kỳ và thuộc bất kỳ loại nào bằng cách tham chiếu:

template<typename T, std::size_t S>
void my_func(T (&arr)[S]) {
   // do stuff
}

chơi với mã

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.