![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| Dmitriy2k |
|
|||
![]() шустрый ![]() Профиль Группа: Участник Сообщений: 96 Регистрация: 6.11.2005 Репутация: нет Всего: нет |
Подскажите, можно ли передать копию массива в функцию?
т.е. обычно мы передаем в функцию как бы указатель на первый элемент массива и выглядит это так: FuncArray(int arr[][20]){ ... } main() { int a[2][20]; FuncArray(a); } мне же нужно чтобы передавалась в функцию копия массива, чтобы можно было в функции изменять значения элементов, не повреждая исходный массив. |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Это сообщение отредактировал(а) bsa - 30.3.2008, 11:40 |
|||
|
||||
| Dennnis |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 145 Регистрация: 23.3.2008 Репутация: нет Всего: 4 |
или
Это сообщение отредактировал(а) Dennnis - 30.3.2008, 11:39 --------------------
Get Rich or Die Tryin' |
||||
|
|||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Dennnis, во втором случае передачи идет по ссылке, по сути, тоже самое, что по указателю.
|
|||
|
||||
| Dennnis |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 145 Регистрация: 23.3.2008 Репутация: нет Всего: 4 |
Ты имеешь ввиду надо так:
--------------------
Get Rich or Die Tryin' |
||||
|
|||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Dennnis, да. Теперь уже передача по значению.
|
|||
|
||||
| Dmitriy2k |
|
|||
![]() шустрый ![]() Профиль Группа: Участник Сообщений: 96 Регистрация: 6.11.2005 Репутация: нет Всего: нет |
Мне не очень понятно что означают угловые скобки. Я сколько писал на Си ни разу не встречал :( [quote] |
|||
|
||||
| bsa |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Это С++. std::vector - это шаблон динамического массива. В этой строчке, в частности, создание массива массивов int. |
||||
|
|||||
| Rififi |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1254 Регистрация: 9.3.2008 Репутация: 11 Всего: 36 |
массив не является указателем на первый элемент а неявно приводится к нему компилятором. вот пример функцмии, в который передаётся сам массив, без потери информации о типе.
|
||||
|
|||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Rififi, читаем вопрос Dmitriy2k внимательно - речь идет о языке Си
|
|||
|
||||
| Rififi |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1254 Регистрация: 9.3.2008 Репутация: 11 Всего: 36 |
bsa,
а чего тогда ему советуют вектор? Для Си кроме отсутствия ссылочного типа ничего не меняется void f(int (*arr)[10]) { printf("%d элементов.\n", sizeof(*arr) / sizeof((*arr)[0])); } int arr[10]; FuncArray(&arr); |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Rififi, ты ему предлагаешь передать по указателю, а ему нужно по значению
|
|||
|
||||
| Rififi |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1254 Регистрация: 9.3.2008 Репутация: 11 Всего: 36 |
чтобы передать "массив по-значению", нужно чтобы он был lvalue и/или имел конструктор копирования.
а массив, как известно, не является lvalue, зато является POD-типом, следовательно, запрашиваемое в исходном вопросе невозможно. |
|||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
||||
|
||||
| Graf_h |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 482 Регистрация: 18.10.2007 Где: г. Ровно, Украина Репутация: 2 Всего: 5 |
Это честно говоря глупо -------------------- Иногда переменная - это просто переменная |
|||
|
||||
| vinter |
|
||||||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
угу, это очень умно, особенно если учесть что
имя массива есть адрес первого элемента, т.е можно считать указателем.
чего? |
||||||
|
|||||||
| Rififi |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1254 Регистрация: 9.3.2008 Репутация: 11 Всего: 36 |
vinter, процитированная фраза - это исключительно моё предположение, потому что я не знаю, что означает "передать массив по-значению".
|
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Похоже, массив действительно нельзя передать по значению. Тогда придется либо через структуру извращаться, либо вручную создавать копию |
|||
|
||||
| JackFlamingo |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 1 Регистрация: 24.6.2007 Репутация: нет Всего: нет |
На мой взгляд, наиболее элегантное решение в отношении переносимости и понимаемости кода - это передать массив по ссылке с модификатором const, а затем ВРУЧНУЮ создать копию.
|
|||
|
||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
||||
|
||||
| MAKCim |
|
||||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
а теперь посмотри ассемблерный листинг как бы мы не старались передать массив по значению, не получится единственный вариант - инкапсуляция
-------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
||||
|
|||||
| Dmitriy2k |
|
|||
![]() шустрый ![]() Профиль Группа: Участник Сообщений: 96 Регистрация: 6.11.2005 Репутация: нет Всего: нет |
Понятно. Спасибо за ответы. Ну чтож единственным вариантом является передача элемента структуры, содержащей массив, в функцию
|
|||
|
||||
| UnrealMan |
|
||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
А создать копию массива внутри функции религия не позволяет?
Имя массива - это не указатель. Затем, что такая передача позволяет контролировать размерность (если она должна быть жёстко задана). Вместо ссылки на массив можно использовать указатель на массив (не путать с указателем на первый элемент). А может, лучше всё-таки в стандарт посмотреть?
Невозможно сделать параметр функции массивом. Всякий параметр, объявление которого выглядит, как объявление массива, на самом деле будет объявленным как указатель. Для массивов не существует copy-initialization, а именно copy-initialization выполняется при передаче параметра:
При отсутствии у массивов copy-initialization функция, параметром которой был бы массив, попросту никогда бы не могла быть вызвана. Это сообщение отредактировал(а) UnrealMan - 1.4.2008, 14:38 |
||||||||
|
|||||||||
| Rififi |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1254 Регистрация: 9.3.2008 Репутация: 11 Всего: 36 |
MAKCim,
листинг доказывает только то, что массив и его первый элемент начинаются с одного адреса, "и чё дальше"?
во-первых, обьясни, что это значит, "массив по значению"? во-вторых, выше была приведена функция, которая получает массив на вход (да-да, именно сам массив, а ни какой не указатель) Это сообщение отредактировал(а) Rififi - 1.4.2008, 15:43 |
||||
|
|||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
причем тут это? причем тут константные ссылки? читай название топика Добавлено через 4 минуты и 42 секунды не будем играть терминами, это практически одно тоже, в случае одномерного. И не надо меня сейчас тыкать стандартом, и с пеной на губах доказывать что я не прав. На практике это работает точно так же, а значит это эквивалент ;) |
|||
|
||||
| UnrealMan |
|
||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Ответ на поставленный в топике вопрос - никак. Всё, что тут можно предложить, - это обходное решение.
ну да, здесь
и здесь
вывод будет практически один и тот же Это сообщение отредактировал(а) UnrealMan - 1.4.2008, 20:46 |
||||||
|
|||||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
UnrealMan, я не говорил что массивы ничем от указателей не отличаются, я сказал что имя массива можно считать указателем(константным). Специфика использования одинакова, и разница между ними не существенна..
|
|||
|
||||
| MAKCim |
|
||||||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
мне достаточно ассемблерного листинга
теперь понятно? если нет, объясню -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
||||||
|
|||||||
| Rififi |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 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 |
|||
|
||||
| baldina |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
Можно. Делаешь копию массива и передаешь ;) Можно наоборот - передаешь исходный, а внутри делаешь копию. В этом случае видимо удобно воспользоваться функций _alloca():
|
||||
|
|||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
||||
|
||||
| Dmitriy2k |
|
|||
![]() шустрый ![]() Профиль Группа: Участник Сообщений: 96 Регистрация: 6.11.2005 Репутация: нет Всего: нет |
||||
|
||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
Dmitriy2k, тут ты объявляешь двойной указатель, а не массив
|
|||
|
||||
| Dmitriy2k |
|
||||
![]() шустрый ![]() Профиль Группа: Участник Сообщений: 96 Регистрация: 6.11.2005 Репутация: нет Всего: нет |
правильней конечно будет так:
а какая разница то компилятор все равно имя массива приводит к указателю(адресу первого элемента массива) смоти ассемблерный код:
|
||||
|
|||||
| Rififi |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1254 Регистрация: 9.3.2008 Репутация: 11 Всего: 36 |
vinter,
внимательно перечитай мое предыдущее сообшение, особенно про операторы sizeof и & Добавлено через 2 минуты и 27 секунд а что тут обьяснять? завалить программу можно разными способами, например так: void f(int**); int arr[10][10]; f((int**) arr); или даже так: int* p = NULL; p[0] = 1; |
|||
|
||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
Rififi, имя массива есть адрес, указатель есть переменная хранящая адрес. Для меня очевидно что эти понятия эквивалентны, даже если в одном есть некоторый функционал отсутсвующий у другого.
к тому же ты привел пример различия, которое используется достаточно редко, а вот то что используется часто работает одинаково. |
|||
|
||||
| MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
я пытаюсь доказать, что в С/С++ массив нельзя передать в функцию по значению ассемблерный код тому подтверждение точка -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |