Здравствуйте, pofig, Вы писали:
P>Салют. P>Объясните плиз как следует понимать конструкцию P>
P>T (&array)[length]
P>
P>Для чего она нужна понятно, а вот что физически происходит и почему нужно писать именно так P>не ясно. Для чего обязательно амперсанд и скобочки?
Амперсанд -- чтобы была ссылка на массив, а скобки -- из-за синтаксиса.
Ссылка нужна потому, что получить массив в качестве параметра нельзя; в C поэтому получали указатель на первый элемент:
void f( int * array );
int main() {
int a[3];
f(a);
}
Здесь при вызове f() происходит "сведение" (decaying) массива к указателю на первый элемент. Очевидно, что информация о размере потеряна.
Зато можно получить указатель на массив нужного размера, например:
void g( int (*array)[3] );
int main() {
int a[3];
g(&a);
}
Сведение здесь не происходит, т.к. передаётся уже указатель на массив.
Зачем здесь скобки -- см. пример ниже:
int* array_of_three_pointers_to_int [ 3 ];
int (*pointer_to_array_of_three_ints) [ 3 ];
Сейчас функция g работает только для массивов из трёх элементов. Обобщаем для любого размера:
template<size_t length>
void h( int (*array)[length] );
int main() {
int a[3];
h(&a);
}
Теперь для вызова шаблонной функции h нужно вывести параметры этого шаблона, за что отвечает вывод типов аргументов (argument type deduction); невероятно умный C++ понимает, что в данном примере length=3.
Ну а так как в C++ есть ссылки и в данном случае они просто удобнее, то можно заменить указатель на ссылку:
template<size_t length>
void hh( int (&array)[length] );
int main() {
int a[3];
hh(a);
}
P> Для чего обязательно амперсанд и скобочки?
Тут шаблон рояли не играет.
амперсанд — это просто объявление ссылки.
скобочки — потому что иначе получится не ссылка на массив, а массив ссылок (который запрещен, но это тут не важно, синтаксически будет именно так). Возникают они из-за того, что в случае массивов и функций тип пишется "вокруг" имени, а не только слева или справа, и непонятно, к чему именно относится звездочка.
С указателем будет то же самое, с точностью до замены амперсанда на звездочку:
int* arr[5]; // массив пяти указателей на интint (*parr)[5]; // указатель на массив из пяти интовint& arr[5]; // массив пяти ссылок на инт (запрещен)int (&rarr)[5]; // ссылка на массив из пяти интовint* f(); // функция, возвращающая указатель на интint (*pf)(); // указатель на функцию, возвращающую интint& f(); // функция, возвращающая ссылку на интint (&rf)(); // ссылка на функцию, возвращающую инт
Проблему с "типом вокруг" можно решить тайпдефом — тогда объявления ссылок и указателей приобретут привычный вид:
typedef int ArrType[5]; // тип: массив из пяти интовtypedef int FuncType(); // тип: функция, возвращающая инт
ArrType* parr; // указатель на массив из пяти интов
ArrType& rarr; // ссылка на массив из пяти интов
FuncType* pf; // указатель на функцию, возвращающую инт
FuncType& rf; // ссылка на функцию, возвращающую инт
Здравствуйте, pofig, Вы писали:
P>Салют. P>Объясните плиз как следует понимать конструкцию P>
P>T (&array)[length]
P>
P> используемую в шаблонах: P>
P>template<typename T, int length>
P>void function(T (&array)[length]) {}
P>
P>Для чего она нужна понятно, а вот что физически происходит и почему нужно писать именно так P>не ясно. Для чего обязательно амперсанд и скобочки?
Таким образом задается ссылка на массив. В данном случае & — это спецификатор ссылки. В С++ массив в функции можно передавать двумя способами. Если в функции параметр объявлен как массив, например, void f( int a[] ), то при передаче массива имя массива преобразуется в указатель на первый элемент массива. А если вы объявили ссылку на массив в качестве параметра void f( int ( &a )[10] ); то в функцию передасться ссылка на массив. То есть внутри функции вы получите алиас вашего исходного массива, который был задан в качестве аргумента при вызове функции. При этом вся информации о массиве будет сохранена.
Сравните два выражения, которые, допустим, присутствуют в теле указанных функция: первая функция sizeof( a ); вторая функция sizeof( a );
Длля первой функции резальтат работы оператора будет равен 4 (на 32 битовой платформе) , то есть размеру указателя, так как в первой функции массив, заданный в качестве аргумента функции преобразуется в указатель на первый элемент массива.
Во второй функции результат работы оператора будет равен 40, так как во второй функции вы имеете дело с самим исходным массивов, заданным алиасом, указанным в качестве имени параметра.
On 12/21/2011 11:04 PM, pofig wrote:
> Объясните плиз как следует понимать конструкцию > > T (&array)[length] > > > используемую в шаблонах: > > template<typename T,int length> > void function(T (&array)[length]) {}
T (&array)[length]
--
объявление 1-го параметра функции function с именем параметра "array"
и типом -- ссылка на массив элементов типа "T" размера "length"
> а вот что физически происходит
Объявляется параметр функции с этим типом и именем.
> и почему нужно писать именно так не ясно.
Чтобы передать параметр именно этого типа и потом можно было бы его использовать.
> Для чего обязательно амперсанд и скобочки?
Амперсанд нужен, чтобы объявить параметр как ссылку, чтобы
параметр не передавался по значению, а только ссылка на данные
передавалась.
Скобочки нужны, чтобы расставить приоритет модификаторов в объявлении.
Без скобочек этот параметр имел бы тип
"массив ссылок на элементы типа "T", размера "length" "
вместо
"ссылка на массив элементов типа "T" размера "length""
Мало того, что семантика типа другая, но кроме этого ещё
в С++ массивы ссылок запрещены, так что без скобок не только
это был бы другой тип, но ещё была бы ошибка компиляции.
Здравствуйте, MasterZiv, Вы писали:
MZ>Кстати, я не знаю, как с массивами ссылок в С++0X
Они запрещены. В рабочем проекте стандарта С++ 2011 написано:
"T is called the array element type; this type shall not be a reference type, the (possibly cvqualified)
type void, a function type or an abstract class type."