• Почему Rider жалуется на выделение памяти при работе со StringBuilder`ом?

    Griboks
    @Griboks Куратор тега C#
    В дополнении к freeExec советую прочитать документацию. Там написано, что append добавляет копию _hello, а также даётся совет указать в конструкторе планируемую ёмкость результирующей строки.
    Ответ написан
    Комментировать
  • Разница в работе памяти и ссылок в C# и Python?

    yarosroman
    @yarosroman Куратор тега C#
    C# the best
    Локальные переменные хранятся на стекле, и им выделяется конкретное место. В случае
    int my_number = 10;
    my_number = 20;

    Перезапишется значение на стеке.

    Да и нникаких оптимизаций при компиляции в байт код не делается, это делает JIT и то при release сборке. Все ненужные присваивания и неиспользуемые переменные выкидываются.
    Ответ написан
    Комментировать
  • Разница в работе памяти и ссылок в C# и Python?

    Griboks
    @Griboks Куратор тега C#
    Разница в работе памяти и ссылок в C# и Python?

    Зависит от версии языка, конкретной реализации виртуальной машины и операционной системы. С этого момента вопрос превращается в гадание на кофейной гуще. Формально следует открыть спецификацию языка и убедиться, что детали реализации не задокументированы.

    ситуация с ссылочными типами должна быть примерно идентична с Питоном

    Да, ситуация очень похожа, и в большинстве случаев так и будет работать. Но как я и предупреждал: "The actual lifetime of a local variable is implementation-dependent."

    Но что происходит, когда я так делаю с value типами?

    В действительности существует 7 категорий переменных, о которых можно прочитать по ссылке.

    Ссылки тут нет (нет же?) и как я понял, то переменная с value типом хранит сам объект, а не ссылку на объект.

    Значимые типы могут содержать ссылки, поэтому сборщик мусора молчаливо удалит лишь оболочку и любезно предоставит вам утечку памяти, но это очень редкий случай. В большинстве случаев можно сказать, что значимая переменная хранит значение. Причём не просто хранит, а копирует его при присваивании ("Assignment to a variable of a value type creates a copy of the value being assigned. ").

    Получается, my_number просто перезапишет значение с 10 на 20 и все?

    Хороший вопрос, но в нём есть подвох. Выражение int my_number = 10; ничего никуда не записывает, а инициализирует - создаёт привязку переменной my_number к ячейке памяти с числом 10 на этапе компиляции. В итоге ваш пример записывает новое значение в переменную всего один раз и завершается.

    Кроме того, это новое значение вовсе и не значение, а литерал. Встаёт ряд вопросов: "Литералы тоже копируются согласно спецификации, или компилятор умнее?" А если компилятор умный, то почему бы ему не объединить этот код в int my_number = 20; на этапе компиляции? Тут уже не лишним и исходники компилятора + виртуальной машины посмотреть.

    Читал про стэк, но ясного понимания пока нет.

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

    p.s.
    На всякий случай хочу заметить, что в питоне тоже не всё так просто и очевидно. Например:
    x = 1; print(id(x))
    x = 2; print(id(x))
    y = 1; print(id(y))
    Ответ написан
    1 комментарий