y6ejushe

Пользователь

Регистрация: 24.10.2021

Сообщения: 12892

Рейтинг: 2185

Нарушения: 15

y6ejushe

Регистрация: 24.10.2021

Сообщения: 12892

Рейтинг: 2185

Нарушения: 15

Заранее извиняюсь за супер тупой вопрос, но я только сейчас это заметил, не знаю как я раньше упускал это с виду. Если передать массив в качестве аргумента функции, то он возвращает измененный массив даже без return. Это потому что во многих языках при передачи массива передается указатель на ячейку памяти, а не сам массив? Я этого раньше даже не замечал, это действительно так? А если я захочу провести расчеты с массивом в функции, но сам массив хочу оставить с теми же числами что и раньше? Не понимаю как я раньше не замечал такого.

 

Руна Дегенерации

Пользователь

Регистрация: 08.04.2021

Сообщения: 556

Рейтинг: 622

Нарушения: 105

Руна Дегенерации

Регистрация: 08.04.2021

Сообщения: 556

Рейтинг: 622

Нарушения: 105

Язык какой сначала скажи.

В JS ты передаёшь ссылку на массив, поэтому если у функции аргументом является массив и ты его меняешь, то и дальше он уже будет изменённый. Но функция при этом ничего не возвращает, ибо return не задан.

y6ejushe

Пользователь

Регистрация: 24.10.2021

Сообщения: 12892

Рейтинг: 2185

Нарушения: 15

y6ejushe

Регистрация: 24.10.2021

Сообщения: 12892

Рейтинг: 2185

Нарушения: 15

Руна Дегенерации сказал(а):

Язык какой сначала скажи.

В JS ты передаёшь ссылку на массив, поэтому если у функции аргументом является массив и ты его меняешь, то и дальше он уже будет изменённый. Но функция при этом ничего не возвращает, ибо return не задан.

Нажмите, чтобы раскрыть...

ruby, да и в с++ я смотрю точно также с vector.

RaiseUP Jahh

Пользователь

Регистрация: 24.06.2020

Сообщения: 490

Рейтинг: 187

RaiseUP Jahh

Регистрация: 24.06.2020

Сообщения: 490

Рейтинг: 187

y6ejushe сказал(а):

Заранее извиняюсь за супер тупой вопрос, но я только сейчас это заметил, не знаю как я раньше упускал это с виду. Если передать массив в качестве аргумента функции, то он возвращает измененный массив даже без return. Это потому что во многих языках при передачи массива передается указатель на ячейку памяти, а не сам массив? Я этого раньше даже не замечал, это действительно так? А если я захочу провести расчеты с массивом в функции, но сам массив хочу оставить с теми же числами что и раньше? Не понимаю как я раньше не замечал такого.

 

Нажмите, чтобы раскрыть...

Делаешь клон массива и работаешь с ним (по крайней мере в java так)

дуфник

Пользователь

Регистрация: 08.04.2013

Сообщения: 3971

Рейтинг: 2983

дуфник

Регистрация: 08.04.2013

Сообщения: 3971

Рейтинг: 2983

в жсе есть у массива в прототипе есть мутабельные методы, которые изменяют массив сам, пример: slice, pop, push..., и иммутабельные, которые создают новый, пример map, sort, filter

дефолтные методы, чтоб клонировать массив в жс - это Array.from(yourArray), и спред: [...yourArray]

Sheodar

Пользователь

Регистрация: 17.09.2020

Сообщения: 306

Рейтинг: 226

Sheodar

Регистрация: 17.09.2020

Сообщения: 306

Рейтинг: 226

img

Если вообще встает задача клонировать массив - может что-то уже пошло не так? pepegahacker.gif?1625805410

drast1c

Пользователь

Регистрация: 02.02.2019

Сообщения: 172

Рейтинг: 75

drast1c

Регистрация: 02.02.2019

Сообщения: 172

Рейтинг: 75

img

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

Но вот по поводу return, то функция всегда строго возвращает либо то, что указано в выражении return, либо ничего, если конечно не была заверешена аварийно.

Jaood

Пользователь

Регистрация: 09.09.2019

Сообщения: 3405

Рейтинг: 2051

Jaood

Регистрация: 09.09.2019

Сообщения: 3405

Рейтинг: 2051

дуфник сказал(а):

в жсе есть у массива в прототипе есть мутабельные методы, которые изменяют массив сам, пример: slice, pop, push..., и иммутабельные, которые создают новый, пример map, sort, filter

дефолтные методы, чтоб клонировать массив в жс - это Array.from(yourArray), и спред: [...yourArray]
Нажмите, чтобы раскрыть...

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

GG WP3

Пользователь

Регистрация: 08.01.2020

Сообщения: 243

Рейтинг: 239

GG WP3

Регистрация: 08.01.2020

Сообщения: 243

Рейтинг: 239

То, что ты назвал, вряд ли является гарантией языка. Скорее всего это undefined behavior. Если ты не указал return, то поведение компилятора стандртом языка скорее всего не определено и в зависимости от компилятора gnu или visual, может сам принимать решение, что делать. Может не скомпилится, может вернуть какую-то фигню, может вообще упасть или выдать ошибку. Закладываться на что-либо нельзя. В твоем случае он видимо достал, что у тебя на стеке функции лежало. Тут я конкретно про плюсы написал

Tofut

Пользователь

Регистрация: 01.12.2021

Сообщения: 60

Рейтинг: 72

Tofut

Регистрация: 01.12.2021

Сообщения: 60

Рейтинг: 72

img

В руби у тебя возвращается последняя выполненная строка в функции, если нет return офк

Тему клоз

E1ektr0

Пользователь

Регистрация: 02.09.2013

Сообщения: 617

Рейтинг: 252

E1ektr0

Регистрация: 02.09.2013

Сообщения: 617

Рейтинг: 252

img
y6ejushe сказал(а):

Заранее извиняюсь за супер тупой вопрос, но я только сейчас это заметил, не знаю как я раньше упускал это с виду. Если передать массив в качестве аргумента функции, то он возвращает измененный массив даже без return. Это потому что во многих языках при передачи массива передается указатель на ячейку памяти, а не сам массив? Я этого раньше даже не замечал, это действительно так? А если я захочу провести расчеты с массивом в функции, но сам массив хочу оставить с теми же числами что и раньше? Не понимаю как я раньше не замечал такого.

 

Нажмите, чтобы раскрыть...

На стеке, значения, масива почти никогда не бывают. Поправьте меня знатоки. Так что да, массив, это сылка на кучу(оперативную память).

Соответственно ты передаёшь в метод ссылку на массив. 

Иногда используют приём - защитное копирование. Делают копию массива, и передают его. В этом случае функция не может модифицировать оригинальный массив.

Tofut сказал(а):

В руби у тебя возвращается последняя выполненная строка в функции, если нет return офк

Тему клоз

Нажмите, чтобы раскрыть...

предположу, никогда не писав на руби, поведение там будет такое же.

GG WP3

Пользователь

Регистрация: 08.01.2020

Сообщения: 243

Рейтинг: 239

GG WP3

Регистрация: 08.01.2020

Сообщения: 243

Рейтинг: 239

E1ektr0 сказал(а):

На стеке, значения, масива почти никогда не бывают. Поправьте меня знатоки. Так что да, массив, это сылка на кучу(оперативную память).

Соответственно ты передаёшь в метод ссылку на массив. 

Иногда используют приём - защитное копирование. Делают копию массива, и передают его. В этом случае функция не может модифицировать оригинальный массив.

 

предположу, никогда не писав на руби, поведение там будет такое же.

Нажмите, чтобы раскрыть...

В плюсах массив в стеке может быть только фиксированного размера, как и все другие переменные. Ведь в противном случае компилятор не сможет заранее понять, где будут находится различные переменные относительно конца стека в разные моменты исполнения программы. Ну и стек тоже находится в оперативной памяти. Просто тут данные хранятся подряд.

E1ektr0

Пользователь

Регистрация: 02.09.2013

Сообщения: 617

Рейтинг: 252

E1ektr0

Регистрация: 02.09.2013

Сообщения: 617

Рейтинг: 252

img
GG WP3 сказал(а):

В плюсах массив в стеке может быть только фиксированного размера, как и все другие переменные. Ведь в противном случае компилятор не сможет заранее понять, где будут находится различные переменные относительно конца стека в разные моменты исполнения программы. Ну и стек тоже находится в оперативной памяти. Просто тут данные хранятся подряд.

Нажмите, чтобы раскрыть...

ну объективно, любой масив фиксированого размера). скажу более, любая переменная. не важно где она находиться. 

скорее речь о том, что большие объекты не хочется размещать в стеке.

а разве стек не в кеше процессора? как минимум на момент исполнения. мне всегда казалось что он там и вытесняется от туда только на свитч потоков.

ну да. ресайз на стеке сделать сложно.

GG WP3

Пользователь

Регистрация: 08.01.2020

Сообщения: 243

Рейтинг: 239

GG WP3

Регистрация: 08.01.2020

Сообщения: 243

Рейтинг: 239

E1ektr0 сказал(а):

ну объективно, любой масив фиксированого размера). скажу более, любая переменная. не важно где она находиться. 

скорее речь о том, что большие объекты не хочется размещать в стеке.

а разве стек не в кеше процессора? как минимум на момент исполнения. мне всегда казалось что он там и вытесняется от туда только на свитч потоков.

Нажмите, чтобы раскрыть...

В момент компиляции должны быть уже известны размеры всех переменных.

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

Например, у нас лежит в стеке два числа и массив на 10 элементов. Ты скомпилировал программу и обратился к первой переменной. Когда ты преобразовал это в ассемблерный код, то программа уже знает, что в какой-то строчке надо на n-байт прыгнуть назад и там будет лежать нужная переменная. В случае динамического размера переменных(например, мы считываем число k и создаем массив на k элементов) в момент преобразования в ассемблерный код мы бы понятия не имели, где будет находится эта переменная относительно конца стека. Мы бы только в момент исполнения программы должны были все это как-то вычислять. Это уже нетривиальные и медленные операции.

Относительно стека понятно, что его данные лучше кэшируются, часть переменных вообще можно на регистры закинуть, чтобы они быстрее работали. Просто размера стека в плюсах можно увеличивать и тогда он никак не поместится в кэш)

 

saw_tooth

Пользователь

Регистрация: 20.08.2013

Сообщения: 5550

Рейтинг: 3286

saw_tooth

Регистрация: 20.08.2013

Сообщения: 5550

Рейтинг: 3286

E1ektr0 сказал(а):

а разве стек не в кеше процессора? как минимум на момент исполнения. мне всегда казалось что он там и вытесняется от туда только на свитч потоков.

Нажмите, чтобы раскрыть...
GG WP3 сказал(а):

Относительно стека понятно, что его данные лучше кэшируются, часть переменных вообще можно на регистры закинуть, чтобы они быстрее работали. Просто размера стека в плюсах можно увеличивать и тогда он никак не поместится в кэш)

Нажмите, чтобы раскрыть...

Нет, стековая память память никакого отношения к кешу процессора не имеет.

 

 

rot1t

Пользователь

Регистрация: 15.01.2016

Сообщения: 5940

Рейтинг: 2136

Нарушения: 104

rot1t

Регистрация: 15.01.2016

Сообщения: 5940

Рейтинг: 2136

Нарушения: 104

y6ejushe сказал(а):

Это потому что во многих языках при передачи массива передается указатель на ячейку памяти, а не сам массив?

Нажмите, чтобы раскрыть...

PepeYes.png?1592048109

 

y6ejushe сказал(а):

А если я захочу провести расчеты с массивом в функции, но сам массив хочу оставить с теми же числами что и раньше?

Нажмите, чтобы раскрыть...

Копируешь

 

y6ejushe сказал(а):

в с++ я смотрю точно также с vector.

Нажмите, чтобы раскрыть...

PepeNo.png?1592048114

 

GG WP3 сказал(а):

В момент компиляции должны быть уже известны размеры всех переменных.

Нажмите, чтобы раскрыть...

PepeNo.png?1592048114

GG WP3

Пользователь

Регистрация: 08.01.2020

Сообщения: 243

Рейтинг: 239

GG WP3

Регистрация: 08.01.2020

Сообщения: 243

Рейтинг: 239

rot1t сказал(а):

PepeYes.png?1592048109

 

Копируешь

 

PepeNo.png?1592048114

 

PepeNo.png?1592048114

Нажмите, чтобы раскрыть...

Почему нет? Ты же не можешь в стек закинуть переменную, у которой заранее неизвестен размер переменной. Ты только можешь положить ссылку на такую переменную. Если нет, то хотелось бы какой-то пример

Pudgewerksaw

Пользователь

Регистрация: 06.01.2021

Сообщения: 2373

Рейтинг: 1027

Нарушения: 90

Pudgewerksaw

Регистрация: 06.01.2021

Сообщения: 2373

Рейтинг: 1027

Нарушения: 90

y6ejushe сказал(а):

Заранее извиняюсь за супер тупой вопрос, но я только сейчас это заметил, не знаю как я раньше упускал это с виду. Если передать массив в качестве аргумента функции, то он возвращает измененный массив даже без return. Это потому что во многих языках при передачи массива передается указатель на ячейку памяти, а не сам массив? Я этого раньше даже не замечал, это действительно так? А если я захочу провести расчеты с массивом в функции, но сам массив хочу оставить с теми же числами что и раньше? Не понимаю как я раньше не замечал такого.

 

Нажмите, чтобы раскрыть...

От языка зависит, в хипстерских языках аля Java, C#, JS да. В C++ допустим надо явно указывать что передаешь по ссылке.

Почему это так? В современных языках не предусматривается возможность неявного копирования, поэтому например в Java не получится сделать копию массива объектов, потому что компилятор не будет знать как скопировать эти самые объекты. В С++ же есть возможность переопределять копирование для собственных типов, а если для объекта не определено копирование то в месте где копируется массив возникнет ошибка компиляции.

rot1t

Пользователь

Регистрация: 15.01.2016

Сообщения: 5940

Рейтинг: 2136

Нарушения: 104

rot1t

Регистрация: 15.01.2016

Сообщения: 5940

Рейтинг: 2136

Нарушения: 104

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

20

Read what VLA are

Press ENTER or type command to continue

 

[@cora ~]$ g++ --version

g++ (GCC) 11.1.0

Kristallo

Пользователь

Регистрация: 13.05.2016

Сообщения: 7709

Рейтинг: 3750

Kristallo

Регистрация: 13.05.2016

Сообщения: 7709

Рейтинг: 3750

img

это на какой мове?

GG WP3

Пользователь

Регистрация: 08.01.2020

Сообщения: 243

Рейтинг: 239

GG WP3

Регистрация: 08.01.2020

Сообщения: 243

Рейтинг: 239

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

20

Read what VLA are

Press ENTER or type command to continue

 

[@cora ~]$ g++ --version

g++ (GCC) 11.1.0
Нажмите, чтобы раскрыть...

Понял, спасибо за информацию. Это возможно, но с большими-большими ограничениями