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

Поиск:

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


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(Graf_h @  31.3.2008,  17:39 Найти цитируемый пост)
Это честно говоря глупо  ! лудше по сonst ссылке  

угу, это очень умно, особенно если учесть что
Цитата(Dmitriy2k @  30.3.2008,  12:29 Найти цитируемый пост)
 чтобы можно было в функцииизменять значения элементов, не повреждая исходный массив.


Цитата(Rififi @  31.3.2008,  00:43 Найти цитируемый пост)
массив не является указателем на первый элемент а неявно приводится к нему компилятором.

имя массива есть адрес первого элемента, т.е можно считать указателем.
Цитата(Rififi @  31.3.2008,  14:40 Найти цитируемый пост)
чтобы передать "массив по-значению", нужно чтобы он был lvalue и/или имел конструктор копирования.

чего?  smile 



--------------------
Мой блог
PM MAIL WWW   Вверх
Rififi
Дата 31.3.2008, 18:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



vinter, процитированная фраза - это исключительно моё предположение, потому что я не знаю, что означает "передать массив по-значению".
PM MAIL   Вверх
bsa
Дата 31.3.2008, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Rififi @ 31.3.2008,  18:37)
vinter, процитированная фраза - это исключительно моё предположение, потому что я не знаю, что означает "передать массив по-значению".

Похоже, массив действительно нельзя передать по значению. Тогда придется либо через структуру извращаться, либо вручную создавать копию
PM   Вверх
JackFlamingo
Дата 31.3.2008, 21:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



На мой взгляд, наиболее элегантное решение в отношении переносимости и понимаемости кода - это передать массив по ссылке с модификатором const, а затем ВРУЧНУЮ создать копию.
PM MAIL ICQ   Вверх
vinter
Дата 31.3.2008, 22:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(JackFlamingo @  31.3.2008,  22:33 Найти цитируемый пост)
На мой взгляд, наиболее элегантное решение в отношении переносимости и понимаемости кода - это передать массив по ссылке с модификатором const

зачем? какой смысл тут от передачи по ссылке?


--------------------
Мой блог
PM MAIL WWW   Вверх
MAKCim
Дата 1.4.2008, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

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



Цитата(bsa @  30.3.2008,  11:38 Найти цитируемый пост)

typedef int Array[2][20];
FuncArray(Array arr)
{
 ....
}
main()
{
    Array a;
    FuncArray(a);
}

а теперь посмотри ассемблерный листинг  smile 

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

typedef struct {
    int array[2][2];
} array_t;



--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Dmitriy2k
Дата 1.4.2008, 09:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


шустрый
*


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

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



Понятно. Спасибо за ответы. Ну чтож единственным вариантом является передача элемента структуры, содержащей массив, в функцию
PM MAIL   Вверх
UnrealMan
Дата 1.4.2008, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(vinter @ 31.3.2008,  18:26)
Цитата(Graf_h @  31.3.2008,  17:39 Найти цитируемый пост)
Это честно говоря глупо  ! лудше по сonst ссылке  

угу, это очень умно, особенно если учесть что
Цитата(Dmitriy2k @  30.3.2008,  12:29 Найти цитируемый пост)
 чтобы можно было в функцииизменять значения элементов, не повреждая исходный массив.

А создать копию массива внутри функции религия не позволяет?

Цитата(vinter @  31.3.2008,  18:26 Найти цитируемый пост)
имя массива есть адрес первого элемента, т.е можно считать указателем.

Имя массива - это не указатель.

Цитата(vinter @  31.3.2008,  22:34 Найти цитируемый пост)
Цитата(JackFlamingo @  31.3.2008,  21:33 Найти цитируемый пост)
На мой взгляд, наиболее элегантное решение в отношении переносимости и понимаемости кода - это передать массив по ссылке с модификатором const, а затем ВРУЧНУЮ создать копию. 

зачем? какой смысл тут от передачи по ссылке?

Затем, что такая передача позволяет контролировать размерность (если она должна быть жёстко задана). Вместо ссылки на массив можно использовать указатель на массив (не путать с указателем на первый элемент).

Цитата(MAKCim @  1.4.2008,  09:22 Найти цитируемый пост)
а теперь посмотри ассемблерный листинг  

А может, лучше всё-таки в стандарт посмотреть?

Цитата(8.3.5 Functions)
After determining the type of each parameter, any parameter of type “array of T” or “function returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” respectively.

Невозможно сделать параметр функции массивом. Всякий параметр, объявление которого выглядит, как объявление массива, на самом деле будет объявленным как указатель. Для массивов не существует copy-initialization, а именно copy-initialization выполняется при передаче параметра:

Цитата(8.5 Initializers)
The initialization that occurs in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and brace-enclosed initializer lists (8.5.1) is called copy-initialization and is equivalent to the form
T x = a;

При отсутствии у массивов copy-initialization функция, параметром которой был бы массив, попросту никогда бы не могла быть вызвана.

Это сообщение отредактировал(а) UnrealMan - 1.4.2008, 14:38
PM MAIL   Вверх
Rififi
Дата 1.4.2008, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



MAKCim, 
 
Цитата
а теперь посмотри ассемблерный листинг

листинг доказывает только то, что массив и его первый элемент начинаются с одного адреса, "и чё дальше"?

Цитата
как бы мы не старались передать массив по значению, не получится

во-первых, обьясни, что это значит, "массив по значению"?
во-вторых, выше была приведена функция, которая получает массив на вход (да-да, именно сам массив, а ни какой не указатель)

Это сообщение отредактировал(а) Rififi - 1.4.2008, 15:43
PM MAIL   Вверх
vinter
Дата 1.4.2008, 19:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(UnrealMan @  1.4.2008,  15:36 Найти цитируемый пост)
А создать копию массива внутри функции религия не позволяет?

причем тут это? причем тут константные ссылки? читай название топика smile  никто не спрашивал "как лучше передать, чтобы потом скопировать"

Добавлено через 4 минуты и 42 секунды
Цитата(UnrealMan @  1.4.2008,  15:36 Найти цитируемый пост)
Имя массива - это не указатель.

не будем играть терминами, это практически одно тоже, в случае одномерного. И не надо меня сейчас тыкать стандартом, и с пеной на губах доказывать что я не прав. На практике это работает точно так же, а значит это эквивалент ;)


--------------------
Мой блог
PM MAIL WWW   Вверх
UnrealMan
Дата 1.4.2008, 20:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(vinter @  1.4.2008,  19:15 Найти цитируемый пост)
никто не спрашивал "как лучше передать, чтобы потом скопировать"

Ответ на поставленный в топике вопрос - никак. Всё, что тут можно предложить, - это обходное решение.

Цитата(vinter @  1.4.2008,  19:15 Найти цитируемый пост)
не будем играть терминами, это практически одно тоже, в случае одномерного.

ну да, здесь

Код

void f(char (&)[100])
{
    std::cout << "array" << std::endl;
}

void f(void *)
{
    std::cout << "pointer" << std::endl;
}

int main()
{
    char arr[100];
    std::cout << sizeof(arr) << std::endl;
    f(arr);
}

и здесь

Код

void f(char (&)[100])
{
    std::cout << "array" << std::endl;
}

void f(void *)
{
    std::cout << "pointer" << std::endl;
}

int main()
{
    char arr[100];
    char *p = arr;
    std::cout << sizeof(p) << std::endl;
    f(p);
}

вывод будет практически один и тот же smile

Это сообщение отредактировал(а) UnrealMan - 1.4.2008, 20:46
PM MAIL   Вверх
vinter
Дата 1.4.2008, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



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


--------------------
Мой блог
PM MAIL WWW   Вверх
MAKCim
Дата 1.4.2008, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

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



Цитата(UnrealMan @  1.4.2008,  14:36 Найти цитируемый пост)
А может, лучше всё-таки в стандарт посмотреть?

мне достаточно ассемблерного листинга

Цитата(Rififi @  1.4.2008,  15:40 Найти цитируемый пост)
листинг доказывает только то, что массив и его первый элемент начинаются с одного адреса, "и чё дальше"?

Код

typedef int array[2][2];

void f2(array a) {
}

void f1(array a) {
    f2(a);
}

int main() {
    array a;
    f1(a);
    return 0;
}

Код

f1:
    push   rbp
    mov    rbp, rsp
    sub    rsp, 8
    mov    qword [rbp - 8], rdi
    mov    rdi, qword [rbp - 8]
    call    f2
    leave
    ret

main:
    push  rbp
    mov   rbp, rsp
    sub   rsp, 16
    lea    rdi, qword [rbp - 16]
    call    f1
    mov    eax, 0
    leave
    ret

теперь понятно?
если нет, объясню



--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Rififi
Дата 1.4.2008, 22:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



vinter, 
Цитата
имя массива можно считать указателем(константным)


int arr[10];

в этой записи имя 'arr' имеет тип 'массив из 10 элементов типа int'. всё. где тут уазатель, покажите мне его? а нету. никакой указатель, константный или нет ни имеет к данной записи ни малейшего отношения. если внутри, в машинном представлении какой-то конкретный компилятор реализует массивы через указатели, как очевидно пытается доказать MAKCim, то я рад за них обоих. только причём здесь C/C++? меня вообще не волнует, что там сидит в машинном коде, да и раздел этот про C/C++.
мифические "указатели" появляются, как только имя arr будет использовано в выражениях. а именно, компилятор приводит имя arr к типу int*. так почему же arr - не указатель? да потому, что такое приведение типов не срабатывает всегда:
1. оператор sizeof(arr) вернет размер, равный 10*sizeof(int), а не sizeof(int*) как это было бы в случае указателя
2. унарный оператор & для выражения &arr имеет тип int(*)[10] а не int**

а результат унарного оператора нужен например затем, чтобы итерироваться по подмассивам:
int arr[10][10];
int (*p)[10] = &a[0];

(*p)[0] = 10; // работаем с первым подмассивом
++p; переходим на следующий подмассив.
(*p)[0] = 20; // продолжаем инициализацию




Это сообщение отредактировал(а) Rififi - 1.4.2008, 22:58
PM MAIL   Вверх
baldina
Дата 1.4.2008, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата

Подскажите, можно ли передать копию массива в функцию?

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

void f (const int* array, size_t count)
{
  size_t size = count * sizeof(int);
  int *temp = (int*)_alloca (size);
  memcpy (temp, array, size);
  // работаем с temp
}

PM MAIL   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0614 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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