Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> передача массива по ссылке, как передать массив в функцию по ссылке 
:(
    Опции темы
Fazil6
Дата 11.6.2007, 13:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



в принципе даже так проканает
Код

#include <stdio.h>

struct AAA
{
    int x;
    int y;
    char t;
    double d;

};
    template<typename T >
void farr(T &as)
{
    printf("\nSize = %d" , sizeof(as)/sizeof(as[0]));
}


int main()
{

    int arr[123];
    farr(arr);

    char ca[12];
    farr(ca);

    AAA ds[12454];
    farr(ds);
}



Ulysses4j, твой вариант скомпилится только для известного размера массива. 

Это сообщение отредактировал(а) Fazil6 - 11.6.2007, 13:19
PM MAIL   Вверх
_stranger_
Дата 11.6.2007, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 52
Регистрация: 3.10.2006
Где: город-герой Киев

Репутация: 2
Всего: 2



а если вот так
Код

int ARR[2][2];
typedef int Mass[2][2];
Mass& ttt = ARR;

void func(Mass &ref)
{
   std::cout << sizeof(ref) << std::endl;
}


PM MAIL   Вверх
Ulysses4j
Дата 11.6.2007, 13:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 304
Регистрация: 6.6.2007
Где: Ростов-на-Дону

Репутация: 4
Всего: 10



Fazil6, мне кажется, что выполнение условия: "размер массива известен на стадии компиляции" (если я правильно понял твои слова) - необходимо для обеих вариантов - шаблонного и нешаблонного. Другое дело, что для массивов разных размеров мой вариант, действительно не подойдет. В случае шаблона генерируется много функций, каждая из которых вроде эквивалентна тому, что я предложил. 

Я не спорю, что шаблонный вариант куда более расширяемый и удобный smile

Это сообщение отредактировал(а) Ulysses4j - 11.6.2007, 13:27


--------------------
Communication is critical to the job of a programmer.
C. Jazdzewski. Fatherly Advice To New Programmers
PM MAIL WWW   Вверх
Fazil6
Дата 11.6.2007, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



Цитата(Ulysses4j @  11.6.2007,  13:25 Найти цитируемый пост)
необходимо для обеих вариантов - шаблонного и нешаблонного.

так, но я имел в виду. что нельзя написать
Код

int sizeOfGivenArr( int (& refArrParam)[])
{
   и т.д. .....

и поэтому для каждого отдельного массива разной размерности придется писать свою функцию, что вобщем-то несовсем входит в условие задачи. Какой смысл определять размер массива внутри функции если он и так жестко задан в объявлении параметра этой функции?
PM MAIL   Вверх
Ulysses4j
Дата 11.6.2007, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 304
Регистрация: 6.6.2007
Где: Ростов-на-Дону

Репутация: 4
Всего: 10



Цитата(Fazil6 @ 11.6.2007,  14:32)
Какой смысл определять размер массива внутри функции если он и так жестко задан в объявлении параметра этой функции?

Мне кажется, именно жесткость здесь и желанна: внутри функции хочется быть уверенным, что мы имеем массив определенного размера. В отличие от распространенного подхода:
Код
void f( int a[3][4] ) {/*...*/}

 - где нам могут подсунуть что-угодно, в случае с ссылками цифры не врут. 

Если на протяжении программы функция вызывается для массива одной и той же длинны, заданной константами, то все нормально - это полностью эквивалентно шаблонному варианту. Под эквивалентностью понимается следующее: если захочется изменить размеры того массива, с которым работает функция - нужно придать новые значения константам и перекомпилировать весь файл - здесь важно, что константы должны находиться в одной единице трансляции, что и вызывающий код и, к тому же, в одной единице трансляции, что и определяемая функция. С шаблонами история такова, что нужно весь шаблон включать в клиентский код (естественно, опять же все вместе перекомпилируется). Еще неизвестно, что удобней.



Это сообщение отредактировал(а) Ulysses4j - 11.6.2007, 13:49


--------------------
Communication is critical to the job of a programmer.
C. Jazdzewski. Fatherly Advice To New Programmers
PM MAIL WWW   Вверх
Fazil6
Дата 11.6.2007, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



Цитата(Ulysses4j @  11.6.2007,  13:46 Найти цитируемый пост)
Еще неизвестно, что удобней.


Цитата(Ulysses4j @  11.6.2007,  13:46 Найти цитируемый пост)
в случае с ссылками цифры не врут.

так причем здесь определение размера? Он ведь известен... В твоем варианте проблема как таковая не стоит.
Код

int sizeOfGivenArr( int (& refArrParam)[ROWS][COLS] ) {
    return sizeof(refArrParam) / sizeof(*refArrParam);
}

это ведь тоже самое что и
Код

int sizeOfGivenArr( int (& refArrParam)[ROWS][COLS] ) {
    return ROWS;
}



PM MAIL   Вверх
Ln78
Дата 11.6.2007, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: 13
Всего: 15



Цитата(zkv @  11.6.2007,  12:51 Найти цитируемый пост)

//а ка провернуть с массивом?
int ARR_A [2][2];

Если размеры известны, то можно писать так:
Код

typedef int Ar2_2[2][2] ;
int ARR_A [2][2];
Ar2_2& rA=ARR_A;

PM MAIL   Вверх
zkv
  Дата 11.6.2007, 23:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: 26
Всего: 92



Всем спасибо, за столь развернутые примеры!

Но полное понимание сего вопроса еще не пришло, посмотрите плиз примерчик:
Код

typedef int Ar2_2[2][2];

int main()
{
    int a = 1, b = 2;
    int &c = (a > b) ? a : b;  //нет проблем

    Ar2_2 ARR_A = {0}, ARR_B = {0};
    
    Ar2_2& rArr1 = ARR_A;//нет проблем
    Ar2_2& rArr2 = (a > b) ? ARR_A : ARR_B; //не катит, почему?
}

на отмеченной проблемной строке компилятор VC7.1 выдает ошибку:
Цитата

main.cpp(12) : error C2440: 'initializing' : cannot convert from 'int (*)[2]' to 'Ar2_2 (&)'
        A reference that is not to 'const' cannot be bound to a non-lvalue

Это особенность компилятора, или это и не должно работать?
PM MAIL   Вверх
Ulysses4j
Дата 11.6.2007, 23:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 304
Регистрация: 6.6.2007
Где: Ростов-на-Дону

Репутация: 4
Всего: 10



zkv, MinGW скомпилировал. VC++ (я восьмеркой пробовал - та же история) выделывается: ссылка - это хоть и константа, но константы бывают времени компиляции и времени выполнения. И если у компилятора не получается на этапе компиляции определить, то надо оставлять на потом. Возможно, правила более хитрые, и я чего-то не понимаю.


--------------------
Communication is critical to the job of a programmer.
C. Jazdzewski. Fatherly Advice To New Programmers
PM MAIL WWW   Вверх
Fazil6
Дата 12.6.2007, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



Цитата(zkv @  11.6.2007,  23:25 Найти цитируемый пост)
Это особенность компилятора, или это и не должно работать?


Цитата(zkv @  11.6.2007,  23:25 Найти цитируемый пост)
на отмеченной проблемной строке компилятор VC7.1 выдает ошибку:

у меня VC 80 проглотил нормально. Насчет VC71. 
Здесь всетаки оператор и видимо какая-то шняга получается с преобразованием массива к указателю (как в параметрах функции) 
Дальше имя массива не lvalue , а чтобы инициализировать ссылку сущностью, которая не является lvalue, эта ссылка должна быть константной (блин задвинул... короче только const ссылки позволяется инициализировать себя не lvalue). Так что понять его можно, хотя повторяю, что 80 схавал нормально
PM MAIL   Вверх
Ulysses4j
Дата 12.6.2007, 07:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 304
Регистрация: 6.6.2007
Где: Ростов-на-Дону

Репутация: 4
Всего: 10



Цитата(Fazil6 @ 12.6.2007,  01:15)
у меня VC 80 проглотил нормально.

Ух-ты, тогда я уточню, что у меня не захотел компилировать этот код с такой же ошибкой компилятор MS Visual C++ 8.0 из состава VS Express Edition. Хотя я все время думал, что сам компилятор EE ничем от оного из "большой" VS не отличается.

Это сообщение отредактировал(а) Ulysses4j - 12.6.2007, 07:28


--------------------
Communication is critical to the job of a programmer.
C. Jazdzewski. Fatherly Advice To New Programmers
PM MAIL WWW   Вверх
Ln78
Дата 12.6.2007, 07:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: 13
Всего: 15



Я пробовал тоже на восьмёрке, профессиональной, выдалась та же ошибка, что и у zkv. Пробовал менять настройки в проекте, что-то не получилось. Пробовал обмануть компилятор в 2 этапа:
Код

typedef int ArD2_3_2[3][2]; //Размерности разные, чтобы было проще отличать их между собой

void FalseReferens()
{
   ArD2_3_2 A={0},B={0};
   int a = 1, b =2;
   int * pI = a < b ? &A[0][0] : &B[0][0];
   ArD2_3_2& rAr = (ArD2_3_2&) pI;

   rAr[1][1]=123; //Здесь изменяется совсем другое значение
}

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

struct Sar
{
   Sar(ArD2_3_2 Ar) : pA(Ar) {}
   inline int* operator[](int i){return  pA[i];}
private:
   int (*pA)[2];
};
void Referens()
{
   ArD2_3_2 A={0},B={0};
   int a = 1, b =2;
   Sar rS = a < b ? A : B;

   rS[1][1]=12;
}

придумать не сумел. Вряд ли это то, что нужно zkv, но, возможно, кому-нибудь и пригодиться.

Это сообщение отредактировал(а) Ln78 - 12.6.2007, 08:09
PM MAIL   Вверх
JackYF
Дата 12.6.2007, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(zkv @  11.6.2007,  13:08 Найти цитируемый пост)
да, наврал немного, ну не суть, пусть будет так:

не будет. Это же совсем не то, что ты хочешь, насколько я понимаю.

Обычно данные проблемы решаются с помощью указателей:
Код


int ARR_A [2][2];
int ARR_B [2][2];


typedef int ARR[2][2];
ARR* rArr;
if( ... )
  rARR = &ARR_A;
else
  rrARR = &ARR_B ;


Неужели так необходимы ссылки?


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
zkv
Дата 12.6.2007, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: 26
Всего: 92



Цитата(JackYF @  12.6.2007,  14:17 Найти цитируемый пост)
не будет. Это же совсем не то, что ты хочешь, насколько я понимаю.

да я наврал много, сразу намека Daevaorn'a не понял smile по привычке делал по аналогии с указателями, потом понял что сморозил чушь.

Цитата(JackYF @  12.6.2007,  14:17 Найти цитируемый пост)
Обычно данные проблемы решаются с помощью указателей:

обычно так и делал, но вот вспомнил слова Страуструпа, что указатели в С++ всегда можно заменить ссылками (где-то он такое говорил...), и решил раскопать, как это делается в таком случае smile
PM MAIL   Вверх
JackYF
Дата 12.6.2007, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(zkv @  12.6.2007,  14:37 Найти цитируемый пост)
что указатели в С++ всегда можно заменить ссылками (где-то он такое говорил...),

ах вот откуда ноги растут... тогда ясно.

Ну я ссылки использую только для сокращения записи переменной, указатели как-то мне проще для понимания в большинстве случаев.



--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Страницы: (4) Все 1 2 [3] 4 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0634 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.