Функции и массивы. Хочу разобраться.

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
Фоб
Сообщения: 45
Зарегистрирован: 10 ноя 2006, 14:56

Функции и массивы. Хочу разобраться.

Сообщение Фоб » 07 дек 2007, 18:56

Я недавно начал изучать С++, и есть непонятки по взаимоотношениям массивов и функций. Буду признателен, если кто-то прояcнит картину.

Вопрос №1:

Объявил функцию типа

Код: Выделить всё

int (& f())[]{

int r[5];

// тут массив каким-то образом заполняется, и затем

return r;

}
Она возвращает ссылку, на созданный в ней массив, но как эту ссылку присвоить переменной?

Пробую совсем прямолинейно:

Код: Выделить всё

int main(){
int m[5];
m = f();
}
Не присваивает, мол, Lvalue подавай. Но блин, если у меня ссылка возвращается функцией, откуда я Lvalue возьму?

Хорошо, работаю с массивом по возвращаемой ссылке поэлементно:

Код: Выделить всё

int main(){
for (i = 0; i < 5; i++){
cout << f()[i]
}
}
Но это ж ужос получается, в этом случае функция f() выполняется на каждом шагу! А если у меня мильён элементов в массиве... Казалось бы, есть в памяти массив значений, есть адрес, в чём проблема, как работать с этим адресом?

В общем, кто что посоветует? Как получить ссылку на массив из функции в виде переменной?

Вопрос №2:

На самом деле функция f() получает в качестве аргументов два массива:

Код: Выделить всё

int (& f(int a[], int b[]))[]{
}
В учебниках пишут, что если вот так передавать массивы в функцию, то создаётся копия этого массива. Проверяю - нихрена подобного!

Код: Выделить всё

int main(){
int a[5], b[5];
f(a, b);
}
Адрес массива a[] внутри функции main() совпадает с адресом массива a[] в функции f(). Делаю вывод, функция работает с оригиналом массива. Получается, в книжках врут? Или это компилятор (CodeGear C++ Builder) опимизирует код?

Да, если это примитивные вопросы и ответ всё-таки легко получить в книжках - так и напишите. Хотя я искал и чё-та не нашёл.

Аватара пользователя
WinMain
Сообщения: 912
Зарегистрирован: 14 янв 2005, 10:30
Откуда: Москва
Контактная информация:

Re: Функции и массивы. Хочу разобраться.

Сообщение WinMain » 07 дек 2007, 22:26

Если хочешь чтобы функция массив возвращала, то массив должен находиться внутри структуры. Объявляешь структуру, создаёшь в ней массив и возвращаешь из функции эту структуру вместе с массивом.
Приглашаю на свой сайт http://winmain.org

ssDev
Сообщения: 50
Зарегистрирован: 20 янв 2005, 14:41

Re: Функции и массивы. Хочу разобраться.

Сообщение ssDev » 11 дек 2007, 19:51

hmm.....
Про Borland ничего говорить не буду, в С++ очень много рахождений между компиляторами, по моему наиболее близкий к стандарту это MS VS C++ 2005

по первому вопросу, у меня компилятор сразу определил ошибку (не говоря о том, что хоть я и давно програмирую на С++ но
конструкции вида int (&f())[]{} не использую)
1. если возврашаеш массив, а не указатель то надо указывать размер int& f()[5]
2. возвращать ссылку на локальную переменную крайне не рекомендуется потому, что эти значения размещаются в стеке и хотя после возврата из функции просто изменяется значение стекового указателя, на самом деле компилятор может там вставить что угодно ,вобщем надо возвращать по значению или
int r[5]
int& f()[5]{... return r;}

по второму
я не знаю про какие учебники ты говориш но C/C++ все переменные передаются по значению, это значит что если ты передаеш в функцию адрес векторв (f(int* x), f(int x[])) то адрес локальной переменной т.е. &x будет разный в вызывающей програме и в вызываемой
но опять же необходимо вспомнить про очень хитро...умные компиляторы
если хочеш понять то
1 надо использовать не CASE системы типа Borland (а ведь не хотел ничего про Borland говорить), а нормальные языковые intel C++, MS C++, gcc
2 компилировать в DEBUG моде, потому что оптимизатор может так изменить программу, что ты ее не узнаеш
3 если уж совсем хочеш в дебри залезть то делай асемблерные листинги и тогда тебе будет все понятно

и того
массивы, переменные это все не важно ты работаеш с памятью. При вызове значения параметров вызова копируются (условно) в локальные переменные функции и никакого влияния на идентификаторы вызывающей функции не оказывают, воообще никакого.
Массив это совершенно обычный идентификатор, просто он указывает на больший обьем памяти например a[10]==*(a+10) нет такой особой вещи как массив. Это беда C/C++ потому что трудно контролировать выход за граници массива (как в других языках) но это и его достоинство!

Фоб
Сообщения: 45
Зарегистрирован: 10 ноя 2006, 14:56

Re: Функции и массивы. Хочу разобраться.

Сообщение Фоб » 15 дек 2007, 13:57

Спасибо, winMain и ssDev, ваши советы мне помогли разобраться. Поэкспериментировав, пришёл к выводу, что, действительно, локальные переменные наружу выводить совершенно не нужно. А лучше давать функции адреса имеющихся переменных.

Кстати,
все переменные передаются по значению, это значит что если ты передаеш в функцию адрес векторв (f(int* x), f(int x[])) то адрес локальной переменной т.е. &x будет разный в вызывающей програме и в вызываемой
Действительно, все переменные передаются по значению. Даже если передаётся адрес памяти. Например void f(int* x) получает значение адреса такое же, какое мы передавали в вызывающей функции: int m[5]; f(m);

И это не зависит от компилятора. А получив адрес, функция пишет туда что захочет например x[0] = 1 - то же самое, что и m[0] = 1 в вызывающей. А значения этого адреса - да, берутся вызывающей и вызываемой функциями из разных точек стека.

Ответить