Массивы в функциях
279
20
Заранее извиняюсь за супер тупой вопрос, но я только сейчас это заметил, не знаю как я раньше упускал это с виду. Если передать массив в качестве аргумента функции, то он возвращает измененный массив даже без return. Это потому что во многих языках при передачи массива передается указатель на ячейку памяти, а не сам массив? Я этого раньше даже не замечал, это действительно так? А если я захочу провести расчеты с массивом в функции, но сам массив хочу оставить с теми же числами что и раньше? Не понимаю как я раньше не замечал такого.
Руна Дегенерации сказал(а):↑Язык какой сначала скажи.
В JS ты передаёшь ссылку на массив, поэтому если у функции аргументом является массив и ты его меняешь, то и дальше он уже будет изменённый. Но функция при этом ничего не возвращает, ибо return не задан.
Нажмите, чтобы раскрыть...ruby, да и в с++ я смотрю точно также с vector.
y6ejushe сказал(а):↑Заранее извиняюсь за супер тупой вопрос, но я только сейчас это заметил, не знаю как я раньше упускал это с виду. Если передать массив в качестве аргумента функции, то он возвращает измененный массив даже без return. Это потому что во многих языках при передачи массива передается указатель на ячейку памяти, а не сам массив? Я этого раньше даже не замечал, это действительно так? А если я захочу провести расчеты с массивом в функции, но сам массив хочу оставить с теми же числами что и раньше? Не понимаю как я раньше не замечал такого.
Нажмите, чтобы раскрыть...Делаешь клон массива и работаешь с ним (по крайней мере в java так)
в жсе есть у массива в прототипе есть мутабельные методы, которые изменяют массив сам, пример: slice, pop, push..., и иммутабельные, которые создают новый, пример map, sort, filter
дефолтные методы, чтоб клонировать массив в жс - это Array.from(yourArray), и спред: [...yourArray]
Вопрос настолько некорректно заданный, что не зная языка, на него невозможно ответить. В общем же, в разных языках программирования есть разные механизмы для реализации указателей, ссылок и прочего синтаксического сахара. Самые гибкие в этом плане пожалуй C++ и C: не вдаваясь в подробности, там можно сделать как угодно: и что бы твой массив менялся, если передается как аргумент, и что бы не менялся, а результат возвращался через return, при чем это можно сделать разными способами. А есть языки, которым такая гибкость (в том числе, возможность прострелить себе ногу лишний раз) вовсе не нужна: например в Python список, он же массив - это изменяемый тип данных, при передаче его как аргумента в функцию, изменение содержимого будет менять сам список, а не его копию.
Но вот по поводу return, то функция всегда строго возвращает либо то, что указано в выражении return, либо ничего, если конечно не была заверешена аварийно.
дуфник сказал(а):↑в жсе есть у массива в прототипе есть мутабельные методы, которые изменяют массив сам, пример: slice, pop, push..., и иммутабельные, которые создают новый, пример map, sort, filter
дефолтные методы, чтоб клонировать массив в жс - это Array.from(yourArray), и спред: [...yourArray]Нажмите, чтобы раскрыть...Оба твоих варианта рабочие только в том случае если массив из примитивов, во всех остальных случаях внутри сохранятся ссылки на оригинальные данные
То, что ты назвал, вряд ли является гарантией языка. Скорее всего это undefined behavior. Если ты не указал return, то поведение компилятора стандртом языка скорее всего не определено и в зависимости от компилятора gnu или visual, может сам принимать решение, что делать. Может не скомпилится, может вернуть какую-то фигню, может вообще упасть или выдать ошибку. Закладываться на что-либо нельзя. В твоем случае он видимо достал, что у тебя на стеке функции лежало. Тут я конкретно про плюсы написал
y6ejushe сказал(а):↑Заранее извиняюсь за супер тупой вопрос, но я только сейчас это заметил, не знаю как я раньше упускал это с виду. Если передать массив в качестве аргумента функции, то он возвращает измененный массив даже без return. Это потому что во многих языках при передачи массива передается указатель на ячейку памяти, а не сам массив? Я этого раньше даже не замечал, это действительно так? А если я захочу провести расчеты с массивом в функции, но сам массив хочу оставить с теми же числами что и раньше? Не понимаю как я раньше не замечал такого.
Нажмите, чтобы раскрыть...На стеке, значения, масива почти никогда не бывают. Поправьте меня знатоки. Так что да, массив, это сылка на кучу(оперативную память).
Соответственно ты передаёшь в метод ссылку на массив. Иногда используют приём - защитное копирование. Делают копию массива, и передают его. В этом случае функция не может модифицировать оригинальный массив.Tofut сказал(а):↑В руби у тебя возвращается последняя выполненная строка в функции, если нет return офк
Тему клоз
Нажмите, чтобы раскрыть...предположу, никогда не писав на руби, поведение там будет такое же.
E1ektr0 сказал(а):↑На стеке, значения, масива почти никогда не бывают. Поправьте меня знатоки. Так что да, массив, это сылка на кучу(оперативную память).
Соответственно ты передаёшь в метод ссылку на массив. Иногда используют приём - защитное копирование. Делают копию массива, и передают его. В этом случае функция не может модифицировать оригинальный массив.
предположу, никогда не писав на руби, поведение там будет такое же.
Нажмите, чтобы раскрыть...В плюсах массив в стеке может быть только фиксированного размера, как и все другие переменные. Ведь в противном случае компилятор не сможет заранее понять, где будут находится различные переменные относительно конца стека в разные моменты исполнения программы. Ну и стек тоже находится в оперативной памяти. Просто тут данные хранятся подряд.
GG WP3 сказал(а):↑В плюсах массив в стеке может быть только фиксированного размера, как и все другие переменные. Ведь в противном случае компилятор не сможет заранее понять, где будут находится различные переменные относительно конца стека в разные моменты исполнения программы. Ну и стек тоже находится в оперативной памяти. Просто тут данные хранятся подряд.
Нажмите, чтобы раскрыть...ну объективно, любой масив фиксированого размера). скажу более, любая переменная. не важно где она находиться.
скорее речь о том, что большие объекты не хочется размещать в стеке.а разве стек не в кеше процессора? как минимум на момент исполнения. мне всегда казалось что он там и вытесняется от туда только на свитч потоков.ну да. ресайз на стеке сделать сложно.
E1ektr0 сказал(а):↑ну объективно, любой масив фиксированого размера). скажу более, любая переменная. не важно где она находиться.
скорее речь о том, что большие объекты не хочется размещать в стеке.а разве стек не в кеше процессора? как минимум на момент исполнения. мне всегда казалось что он там и вытесняется от туда только на свитч потоков.Нажмите, чтобы раскрыть...В момент компиляции должны быть уже известны размеры всех переменных.
Там же весь прикол в том, что для быстрой работы стека программа должна заранее знать, где будет находится какая переменная.
Например, у нас лежит в стеке два числа и массив на 10 элементов. Ты скомпилировал программу и обратился к первой переменной. Когда ты преобразовал это в ассемблерный код, то программа уже знает, что в какой-то строчке надо на n-байт прыгнуть назад и там будет лежать нужная переменная. В случае динамического размера переменных(например, мы считываем число k и создаем массив на k элементов) в момент преобразования в ассемблерный код мы бы понятия не имели, где будет находится эта переменная относительно конца стека. Мы бы только в момент исполнения программы должны были все это как-то вычислять. Это уже нетривиальные и медленные операции.
Относительно стека понятно, что его данные лучше кэшируются, часть переменных вообще можно на регистры закинуть, чтобы они быстрее работали. Просто размера стека в плюсах можно увеличивать и тогда он никак не поместится в кэш)
E1ektr0 сказал(а):↑а разве стек не в кеше процессора? как минимум на момент исполнения. мне всегда казалось что он там и вытесняется от туда только на свитч потоков.
Нажмите, чтобы раскрыть...GG WP3 сказал(а):↑Относительно стека понятно, что его данные лучше кэшируются, часть переменных вообще можно на регистры закинуть, чтобы они быстрее работали. Просто размера стека в плюсах можно увеличивать и тогда он никак не поместится в кэш)
Нажмите, чтобы раскрыть...Нет, стековая память память никакого отношения к кешу процессора не имеет.
y6ejushe сказал(а):↑Это потому что во многих языках при передачи массива передается указатель на ячейку памяти, а не сам массив?
Нажмите, чтобы раскрыть...
y6ejushe сказал(а):↑А если я захочу провести расчеты с массивом в функции, но сам массив хочу оставить с теми же числами что и раньше?
Нажмите, чтобы раскрыть...Копируешь
y6ejushe сказал(а):↑в с++ я смотрю точно также с vector.
Нажмите, чтобы раскрыть...
GG WP3 сказал(а):↑В момент компиляции должны быть уже известны размеры всех переменных.
Нажмите, чтобы раскрыть...
y6ejushe сказал(а):↑Заранее извиняюсь за супер тупой вопрос, но я только сейчас это заметил, не знаю как я раньше упускал это с виду. Если передать массив в качестве аргумента функции, то он возвращает измененный массив даже без return. Это потому что во многих языках при передачи массива передается указатель на ячейку памяти, а не сам массив? Я этого раньше даже не замечал, это действительно так? А если я захочу провести расчеты с массивом в функции, но сам массив хочу оставить с теми же числами что и раньше? Не понимаю как я раньше не замечал такого.
Нажмите, чтобы раскрыть...От языка зависит, в хипстерских языках аля Java, C#, JS да. В C++ допустим надо явно указывать что передаешь по ссылке.
Почему это так? В современных языках не предусматривается возможность неявного копирования, поэтому например в Java не получится сделать копию массива объектов, потому что компилятор не будет знать как скопировать эти самые объекты. В С++ же есть возможность переопределять копирование для собственных типов, а если для объекта не определено копирование то в месте где копируется массив возникнет ошибка компиляции.
GG WP3 сказал(а):↑Почему нет? Ты же не можешь в стек закинуть переменную, у которой заранее неизвестен размер переменной. Ты только можешь положить ссылку на такую переменную. Если нет, то хотелось бы какой-то пример
Нажмите, чтобы раскрыть...#include "iostream"
void foo(int size)
{ int a; std::cout << sizeof(a) << std::endl; return;}
int main()
{ foo(1); foo(5); std::cout << "Read what VLA are" << std::endl;
return 0;
}
:!g++ main.cpp && ./a.out
4
20Read what VLA arePress ENTER or type command to continue
[@cora ~]$ g++ --version
g++ (GCC) 11.1.0
rot1t сказал(а):↑#include "iostream"
void foo(int size){ int a; std::cout << sizeof(a) << std::endl; return;}
int main()
{ foo(1); foo(5); std::cout << "Read what VLA are" << std::endl;
return 0;
}
:!g++ main.cpp && ./a.out
4
20Read what VLA arePress ENTER or type command to continue
[@cora ~]$ g++ --versiong++ (GCC) 11.1.0
Нажмите, чтобы раскрыть...Понял, спасибо за информацию. Это возможно, но с большими-большими ограничениями
Тема закрыта
-
ЗаголовокОтветов ПросмотровПоследнее сообщение
-
Сообщений:6
Просмотров:8
-
Сообщений:7
Просмотров:7
-
Сообщений:1
Просмотров:2
-
Тимур Латыпов (2) 26 Apr 2024 в 18:49Сообщений: 6 26 Apr 2024 в 18:49
Сообщений:6
Просмотров:8
-
Сообщений:14
Просмотров:20