2010-04-02 4 views
1

Реф. к моему last post и комментарию sellibitze к этому сообщению о передаче массива с помощью ref, а не по значению, почему это так, что когда я передаю массив по значению, компилятор может выводить аргументы, но он не будет делать этого, если я передам его по значению?Проходящий массив по реф.

template<class T,int row, int col> 
void invert(T (&a)[row][col]) //NOTE AMPERSAND 

в основном с декларацией выше, я могу назвать:

int main(int argc, char* argv[]) 
{ 
invert(a);//HERE ARGUMETS ARE AUTOMATICALLY DEDUCED 
} 

, но без амперсанд я бы называть это так:

int main(int argc, char* argv[]) 
    { 
    invert<int,3,4>(a); 
    } 

@Paul Так просто, чтобы понять, когда я объявляю fnc:

void f(int a[]);//I'm passing a pointer 

, но когда я объявляю:

void f(int &a[]);//I'm passing a ref? 

ли я понимаю, это правильно сейчас?

+4

Вы не можете передать массив по значению в C++ - вы передаете только указатель или ссылку –

+0

[передача массивов указателем по ссылке] (http://stackoverflow.com/questions/2559896/how-are -arrays-pass/2560474 # 2560474) – fredoverflow

+0

Разъясняется здесь: http://stackoverflow.com/questions/437150/can-someone-explain-this-template-code-that-gives-me-the-size-of-an -array –

ответ

3

Это потому что, когда вы передаете массив «по значению», он распадается на указатель. То есть вы фактически передаете указатель на первый элемент без какой-либо информации о размере.

Если у вас есть подпись, как это:

void foo(int arr[10]); 

то значение 10 полностью игнорируется, и вы можете передать массивы Интс любого размера к нему. Это точно так же, как и

void foo(int arr[]); 

или

void foo(int* arr); 

Как вы можете видеть информацию о размере не сохраняется, и поэтому он не может быть использован, чтобы вывести размер массива.

С двумерным массивом первое измерение распадается. Например: массив из 10 массивов из 20 целых чисел (int arr[10][20]) распадается на указатель на массивы из 20 целых чисел (int (*arr)[20]) и т. Д., Поэтому значение 10 не может быть выведено, но размер второго измерения (20) сохраняется. выводится.

template<class T,int row, int col> 
void foo(T (&a)[row][col]) { } 

template <class T, int col> 
void bar(T arr[][col]) {} 

int main() 
{ 
    int a[10][20]; 
    foo(a); 
    bar(a); 
} 

Когда вы что-то передать по ссылке, сохраняется типа, массивы не гниют и вся информация размера будет оставаться доступной.

1

Вы не можете передать массив по значению, только указателем (когда вы передаете массив функции, которая автоматически преобразуется в указатель).

Я не совсем понимаю, что вы подразумеваете под «выводом аргументов»; вы имеете в виду общий размер массива? Если да, то если вы передаете его указателем, он потерян, потому что указатели не несут такую ​​информацию.

Anyways I настоятельно рекомендует использовать std::vector, а не обычные старые массивы С; гораздо меньше головных болей! По умолчанию они передаются по значению (как и следовало ожидать); они могут легко передаваться по ссылке и указателем, если вы хотите, и они никогда не теряют информацию, такую ​​как размер массива. Они также защищаются от переполнения буфера и нижних потоков, и они автоматически растут по мере добавления дополнительных элементов.

+0

Проверить мое сообщение Я добавил объявление fnc. –

+0

О, я понимаю, что вы сейчас имеете в виду. В любом случае следуйте моему предложению и используйте std :: vector! –

1
void f(int &a[]); // I'm passing a ref? 

Нет, здесь вы пытаетесь передать массив ссылок, который не существует в системе типа. Возможно, возникнет соблазн написать следующее:

void f(int (&a)[]); 

Но ссылки на массивы неизвестных границ не допускаются в качестве параметров функции.


При объявлении параметр функции как массив п измерений, оно переписывается компилятором как указатель на массив из п-1 измерений. Следующие подписи эквивалентны:

void fun(int x[][10]); 
void fun(int x[2][10]); 
void fun(int x[99][10]); 
void fun(int (*x)[10]); 

Связанный первого измерения игнорируется, и, таким образом, не может быть выведен с помощью механизма шаблона.

Что вы можете сделать, это передать указатель на весь массив 2D:

template <class T, int row, int col> 
void invert(T (*a)[row][col]) 
{ 
    std::cout << row << " x " << col << std::endl; 
    T first_entry = (*a)[0][0]; 
} 

int main(int argc, char* argv[]) 
{ 
    int a[10][20]; 
    invert(&a); 
} 

Это работает, как ожидалось, но как вы можете видеть, синтаксис немного неуклюжий с обеих сторон.

+0

«Но ссылки на массивы неизвестных границ тоже не существуют» Я не думаю, что это правда. Они просто запрещены как параметры, если я правильно помню. Другими словами, 'extern int a []; int (& ar) [] = a; 'отлично. –

+0

@Johannes Спасибо, исправлено. – fredoverflow

Смежные вопросы