Swift | Вопросы собесов
2.13K subscribers
28 photos
949 links
Download Telegram
🤔 Какие есть паттерны в объектном проектировании

Среди паттернов объектного проектирования выделяются: порождающие паттерны (например, Singleton, Factory, Builder), структурные паттерны (Adapter, Composite, Decorator) и поведенческие паттерны (Observer, Strategy, Command). Порождающие паттерны помогают создавать объекты, структурные организуют отношения между объектами, а поведенческие управляют взаимодействиями и обязанностями объектов. Эти паттерны способствуют созданию гибкого и поддерживаемого кода.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что использовать вместо наследования для расширения класса?

Использование наследования для расширения класса может привести к жесткой связности и сложностям в поддержке кода. Вместо наследования можно использовать следующие альтернативы: композиция, протоколы (интерфейсы), категории (extensions) и делегирование. Эти подходы предлагают большую гибкость и модульность, уменьшая вероятность проблем, связанных с наследованием.

🟠Композиция
Композиция предполагает включение объектов других классов в качестве полей и делегирование им работы. Это позволяет комбинировать различные компоненты и изменять их поведение во время выполнения.
protocol Engine {
func start()
}

class Car {
private let engine: Engine

init(engine: Engine) {
self.engine = engine
}

func start() {
engine.start()
}
}

class ElectricEngine: Engine {
func start() {
print("Electric engine starting...")
}
}

class GasolineEngine: Engine {
func start() {
print("Gasoline engine starting...")
}
}

let electricCar = Car(engine: ElectricEngine())
let gasolineCar = Car(engine: GasolineEngine())
electricCar.start() // Electric engine starting...
gasolineCar.start() // Gasoline engine starting...


🟠Протоколы и интерфейсы
Протоколы определяют набор методов и свойств, которые класс или структура должны реализовать. Это позволяет создавать гибкие и переиспользуемые компоненты.
protocol Drawable {
func draw()
}

class Circle: Drawable {
func draw() {
print("Drawing a circle")
}
}

class Square: Drawable {
func draw() {
print("Drawing a square")
}
}

func render(drawable: Drawable) {
drawable.draw()
}

let shapes: [Drawable] = [Circle(), Square()]
shapes.forEach { render(drawable: $0) }


🟠Категории и расширения (Extensions)
Расширения позволяют добавлять новые методы и свойства к существующим классам, структурам или перечислениям без необходимости наследования или изменения исходного кода.
extension String {
func reverse() -> String {
return String(self.reversed())
}
}

let original = "hello"
let reversed = original.reverse()
print(reversed) // "olleh"


🟠Делегирование
Делегирование предполагает передачу ответственности за выполнение определенных задач другому объекту. Это часто используется для создания гибких и переиспользуемых компонентов.
protocol PrinterDelegate: AnyObject {
func printerDidFinishPrinting(_ printer: Printer)
}

class Printer {
weak var delegate: PrinterDelegate?

func printDocument() {
// Печать документа
print("Printing document...")
// Уведомление делегата о завершении печати
delegate?.printerDidFinishPrinting(self)
}
}

class PrintManager: PrinterDelegate {
func printerDidFinishPrinting(_ printer: Printer) {
print("Document printing completed.")
}
}

let printer = Printer()
let manager = PrintManager()

printer.delegate = manager
printer.printDocument()
// "Printing document..."
// "Document printing completed."


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Расскажи о самом главном различии между UI Vue и CLI Vue

UI Vue предоставляет графический интерфейс для работы с проектами Vue, управляя настройками и сборками через визуальный интерфейс. CLI Vue — это командная строка, с помощью которой разработчики могут создавать и управлять проектами Vue через текстовые команды, имея более детальный контроль над конфигурацией. Основное различие — способ взаимодействия: UI Vue удобен для новичков, а CLI Vue подходит для более гибкой и точной настройки.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👾5😁2
🤔 Как бы сделал MVP со SwiftUI?

Это архитектурный шаблон, который разделяет логику приложения на три компонента: Model, View и Presenter. Несмотря на то, что SwiftUI тесно интегрирован с архитектурой MVVM (Model-View-ViewModel), можно адаптировать его для использования с MVP. В этом примере я покажу, как можно реализовать MVP со SwiftUI.

🚩Структура проекта

- Models
- User.swift
- Views
- UserView.swift
- Presenters
- UserPresenter.swift


🚩Шаги по созданию MVP со SwiftUI

1⃣Model
Модель представляет данные и бизнес-логику. В нашем примере это будет простая структура User.
struct User {
let name: String
let age: Int
}


2⃣Presenter
Презентер управляет логикой представления и взаимодействует с моделью. Он обновляет представление в ответ на изменения данных.
protocol UserPresenterProtocol {
var user: User? { get }
func fetchUser()
}

class UserPresenter: ObservableObject, UserPresenterProtocol {
@Published var user: User?

func fetchUser() {
// Логика получения данных пользователя (например, из сети или базы данных)
self.user = User(name: "John Doe", age: 30)
}
}


3⃣View
Представление отвечает за отображение данных и взаимодействие с пользователем. В SwiftUI представление использует @StateObject или @ObservedObject для наблюдения за изменениями данных в презентере.
import SwiftUI

struct UserView: View {
@StateObject var presenter = UserPresenter()

var body: some View {
VStack {
if let user = presenter.user {
Text("Name: \(user.name)")
Text("Age: \(user.age)")
} else {
Text("Loading...")
}
}
.onAppear {
presenter.fetchUser()
}
}
}

struct UserView_Previews: PreviewProvider {
static var previews: some View {
UserView()
}
}


🚩Полный пример

User.swift
struct User {
let name: String
let age: Int
}


UserPresenter.swift
protocol UserPresenterProtocol {
var user: User? { get }
func fetchUser()
}

class UserPresenter: ObservableObject, UserPresenterProtocol {
@Published var user: User?

func fetchUser() {
// Логика получения данных пользователя (например, из сети или базы данных)
self.user = User(name: "John Doe", age: 30)
}
}


UserView.swift
import SwiftUI

struct UserView: View {
@StateObject var presenter = UserPresenter()

var body: some View {
VStack {
if let user = presenter.user {
Text("Name: \(user.name)")
Text("Age: \(user.age)")
} else {
Text("Loading...")
}
}
.onAppear {
presenter.fetchUser()
}
}
}

struct UserView_Previews: PreviewProvider {
static var previews: some View {
UserView()
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👀1
🤔 Сколько может быть куч и стеков в приложении

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6🤯1
🤔 Что делает Synchronized?

Synchronized в программировании используется для управления доступом к ресурсам в многопоточном окружении, чтобы предотвратить состояние гонки (race condition). В контексте iOS и Swift, Synchronized гарантирует, что только один поток может выполнять определенный блок кода в любой момент времени.

🚩Пример

🟠С использованием `NSLock`
В данном примере, NSLock используется для синхронизации доступа к переменной internalState. Метод increment() увеличивает значение переменной на единицу, и блок lock/unlock гарантирует, что этот код выполнится атомарно, то есть только один поток сможет его выполнять в один момент времени. Тоже самое относится к методу getState(), который возвращает текущее значение переменной.
class ThreadSafeClass {
private var internalState = 0
private let lock = NSLock()

func increment() {
lock.lock()
internalState += 1
lock.unlock()
}

func getState() -> Int {
lock.lock()
let state = internalState
lock.unlock()
return state
}
}


🟠С использованием `DispatchQueue`
В этом примере DispatchQueue с атрибутом sync используется для обеспечения того, что блок кода внутри будет выполнен синхронно, то есть только один поток сможет выполнить его в данный момент времени.
class ThreadSafeClass {
private var internalState = 0
private let queue = DispatchQueue(label: "com.example.threadSafeQueue")

func increment() {
queue.sync {
internalState += 1
}
}

func getState() -> Int {
return queue.sync {
internalState
}
}
}


🟠С использованием `@synchronized` из Objective-C
Здесь objc_sync_enter(self) и objc_sync_exit(self) обеспечивают блокировку и разблокировку доступа к ресурсу.
class ThreadSafeClass: NSObject {
private var internalState = 0

func increment() {
objc_sync_enter(self)
internalState += 1
objc_sync_exit(self)
}

func getState() -> Int {
objc_sync_enter(self)
let state = internalState
objc_sync_exit(self)
return state
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1
🤔 Какие есть два типа инициализаторов?

Существует два типа инициализаторов: статические и нестатические.
Статические инициализаторы (`static`) выполняются один раз при загрузке класса и инициализируют статические переменные.
Нестатические инициализаторы выполняются при создании каждого экземпляра класса и используются для инициализации нестатических переменных.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
🤔 Чем отличается композиция от наследования?

Использование наследования может привести к жесткой связности и сложностям в поддержке кода. Альтернативы наследованию: композиция, протоколы (интерфейсы), расширения (extensions) и делегирование. Эти подходы обеспечивают большую гибкость и модульность.

🟠Композиция
Композиция включает объекты других классов как поля и делегирует им работу, что позволяет гибко изменять поведение во время выполнения.
protocol Engine {
func start()
}

class Car {
private let engine: Engine

init(engine: Engine) {
self.engine = engine
}

func start() {
engine.start()
}
}

class ElectricEngine: Engine {
func start() {
print("Electric engine starting...")
}
}

class GasolineEngine: Engine {
func start() {
print("Gasoline engine starting...")
}
}

let electricCar = Car(engine: ElectricEngine())
let gasolineCar = Car(engine: GasolineEngine())
electricCar.start()
gasolineCar.start()


🟠Протоколы и интерфейсы
Протоколы определяют набор методов и свойств, которые класс или структура должны реализовать, обеспечивая гибкость и переиспользуемость компонентов.
protocol Drawable {
func draw()
}

class Circle: Drawable {
func draw() {
print("Drawing a circle")
}
}

class Square: Drawable {
func draw() {
print("Drawing a square")
}
}

func render(drawable: Drawable) {
drawable.draw()
}

let shapes: [Drawable] = [Circle(), Square()]
shapes.forEach { render(drawable: $0) }


🟠Категории и расширения (Extensions)
Расширения добавляют новые методы и свойства к существующим классам, структурам или перечислениям без изменения исходного кода.
extension String {
func reverse() -> String {
return String(self.reversed())
}
}

let original = "hello"
let reversed = original.reverse()
print(reversed) // "olleh"


🟠Делегирование
Делегирование передает ответственность за выполнение задач другому объекту, создавая гибкие и переиспользуемые компоненты.
protocol PrinterDelegate: AnyObject {
func printerDidFinishPrinting(_ printer: Printer)
}

class Printer {
weak var delegate: PrinterDelegate?

func printDocument() {
print("Printing document...")
delegate?.printerDidFinishPrinting(self)
}
}

class PrintManager: PrinterDelegate {
func printerDidFinishPrinting(_ printer: Printer) {
print("Document printing completed.")
}
}

let printer = Printer()
let manager = PrintManager()

printer.delegate = manager
printer.printDocument()


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
🤔 Как проявляется отличие валью тайпа от референса когда пишем код?

Value type (тип значения) хранит данные непосредственно, и при копировании создаётся новый независимый экземпляр. Например, в C# типы `int` или `struct` копируются по значению.
Reference type (ссылочный тип) хранит ссылку на область памяти, где находятся данные, и при копировании копируется только ссылка, а не сами данные. Например, объекты классов разделяют одну и ту же память.
Разница проявляется при изменении данных: value type остаётся неизменным в копиях, а reference type отражает изменения во всех ссылках.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Чем отличается класс user от класса data?

В объектно-ориентированном программировании классы могут выполнять различные роли в зависимости от их назначения и использования. Классы, условно названные User и Data, могут иметь существенные различия в своей реализации и предназначении.

🚩Класс `User`

Класс User обычно представляет сущность пользователя в системе. Он может включать свойства и методы, специфичные для пользователя, такие как идентификатор, имя, адрес электронной почты и методы для управления этими данными.
class User {
var id: Int
var name: String
var email: String

init(id: Int, name: String, email: String) {
self.id = id
self.name = name
self.email = email
}

func updateEmail(newEmail: String) {
self.email = newEmail
}
}


🚩Основные характеристики

🟠Содержит данные, специфичные для пользователя.
🟠Может включать методы для управления данными пользователя.
🟠Часто используется в бизнес-логике приложения.

🚩Класс `Data`

Класс Data чаще всего используется для представления необработанных данных или байтов. В Swift, например, Data — это структура из Foundation, которая предоставляет интерфейс для работы с бинарными данными.
import Foundation

let string = "Hello, World!"
if let data = string.data(using: .utf8) {
// Преобразование строки в Data
print(data)
}

let jsonString = "{\"name\": \"John\", \"age\": 30}"
if let jsonData = jsonString.data(using: .utf8) {
// Преобразование JSON-строки в Data
do {
if let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
print(jsonObject)
}
} catch {
print("Ошибка парсинга JSON: \(error)")
}
}


🚩Основные характеристики

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

🚩Ключевые различия

🟠Назначение и область применения
User: Представляет конкретную сущность пользователя в системе. Используется для управления и хранения данных о пользователе.
Data: Представляет необработанные данные или байты. Используется для операций с бинарными данными, таких как чтение и запись файлов, сетевые операции и сериализация.

🟠Состав и структура
User: Обычно содержит несколько свойств, специфичных для пользователя, и методы для управления этими данными.
Data: Является универсальным контейнером для байтов, предоставляя методы для работы с этими данными.

🟠Использование в приложении
User: Включен в бизнес-логику, тесно связан с функциональностью приложения, связанной с пользователями.
Data: Используется для низкоуровневых операций с данными, часто не связан напрямую с бизнес-логикой.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1😁1
🤔 В чем суть оптимизации copy on write?

Copy on Write (COW) — это оптимизация, которая откладывает копирование данных до тех пор, пока они не будут изменены. В Swift, структуры и коллекции используют эту технику, чтобы избежать ненужных копий, если данные остаются неизменными. Когда структура или коллекция копируется, реальное копирование происходит только при попытке изменить данные, что снижает накладные расходы. Это помогает улучшить производительность и снизить использование памяти.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу Знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Почему приложения массивные?

Приложения на Swift могут быть массивными из-за нескольких факторов:

🚩Причины

🟠Стандартная библиотека
Включает много функций и структур данных, что увеличивает размер бинарного файла.
🟠Архитектура приложения
Современные приложения часто используют множество внешних библиотек и фреймворков, добавляющих объем.
🟠Поддержка нескольких архитектур
Компиляция для разных архитектур (например, arm64, x86_64) увеличивает размер исполняемого файла.
🟠Ресурсы и медиафайлы
Большое количество изображений, видео и аудиофайлов увеличивают размер приложения.
🟠Символы отладки
Включение символов отладки для разработки и анализа сбоев добавляет объем.
🟠Статические библиотеки
Статические библиотеки увеличивают размер исполняемого файла по сравнению с динамическими.
🟠Кросс-компиляция
Поддержка старых версий iOS требует включения дополнительных библиотек и кода.

🚩Оптимизация размера

🟠Удаление ненужных архитектур
Использование инструментов для удаления лишних архитектур из финальной сборки.
🟠Оптимизация ресурсов
Сжатие изображений и видео, использование эффективных форматов.
🟠Удаление символов отладки
Исключение символов отладки в релизной сборке.
🟠Динамические библиотеки
Использование динамических библиотек для уменьшения размера основного исполняемого файла.
🟠Рефакторинг кода
Удаление неиспользуемого кода и зависимостей.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое value types?

Value types в Swift — это типы данных, которые копируются при передаче в другую переменную или константу. Примеры value types включают структуры (struct), перечисления (enum) и встроенные типы данных, такие как Int и String. Когда вы изменяете копию value type, оригинальная переменная остаётся неизменной. Это поведение помогает избегать неожиданных изменений данных при работе с несколькими переменными.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Чем опасна команда PO?

🟠Побочные эффекты
PO вызывает методы description или debugDescription, которые могут изменять состояние объекта.

🟠Производительность
Тяжелые вычисления в методах description или debugDescription могут замедлить отладку.

🟠Проблемы с потоками
Доступ к объекту в многопоточной среде может привести к состоянию гонки.

🟠Краш приложения
Ошибки в методах description или debugDescription могут привести к сбоям при использовании PO.

🟠Зависания
Методы, использующие блокировки, могут привести к зависанию отладчика.

🚩Примеры проблем

Побочные эффекты
class DangerousObject {
var counter = 0
var description: String {
counter += 1 // Изменение состояния
return "Counter: \(counter)"
}
}


Производительность
class HeavyObject {
var description: String {
let result = (0..<1_000_000).map { $0 * $0 }.reduce(0, +)
return "Result: \(result)"
}
}


Проблемы с потоками
class ThreadUnsafeObject {
var data = [Int]()
var description: String {
return "Data count: \(data.count)"
}
}


Краш приложения
class CrashObject {
var description: String {
fatalError("Should not be called")
}
}


Зависания
class LockObject {
let lock = NSLock()
var description: String {
lock.lock()
defer { lock.unlock() }
return "Locked"
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Какие есть два типа инициализаторов?

Инициализаторы бывают параметризированные, принимающие значения для установки свойств, и дефолтные, которые автоматически инициализируют свойства значениями по умолчанию.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое IRC?

Это текстовый протокол для общения в реальном времени. Он позволяет пользователям обмениваться сообщениями в каналах (чат-румах) или через личные сообщения.

🚩Характеристики

🟠Каналы
Объединяют пользователей для обсуждения общих тем.
🟠Личные сообщения
Прямой обмен сообщениями между пользователями.
🟠Серверы
Поддерживают несколько каналов и управляют соединениями пользователей.
🟠Клиенты
Программы, используемые для подключения к IRC-серверам и участия в чатах.

🚩Примеры использования

🟠Подключение к IRC-серверу.
🟠Вход в канал (например, #example).
🟠Обмен сообщениями с другими пользователями в канале или через личные сообщения.

🚩Плюсы

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

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Как в Swift устроена инкапсуляция?

Инкапсуляция реализуется через модификаторы доступа (private, fileprivate, internal, public, open), ограничивающие доступ к свойствам и методам. Это позволяет контролировать, какие части кода могут изменять данные объекта.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Как работает Synchronized "под капотом"?

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

🚩Механизмы реализации Synchronized

Различные механизмы синхронизации реализуют Synchronized по-разному, но общая идея заключается в использовании блокировок (локов), чтобы обеспечить эксклюзивный доступ к ресурсу.

🟠NSLock
Это простая блокировка, предоставляемая Foundation framework в Swift:
class ThreadSafeClass {
private var internalState = 0
private let lock = NSLock()

func increment() {
lock.lock()
internalState += 1
lock.unlock()
}

func getState() -> Int {
lock.lock()
let state = internalState
lock.unlock()
return state
}
}


🟠DispatchQueue
DispatchQueue позволяет организовать выполнение кода в синхронном или асинхронном режиме.
class ThreadSafeClass {
private var internalState = 0
private let queue = DispatchQueue(label: "com.example.threadSafeQueue")

func increment() {
queue.sync {
internalState += 1
}
}

func getState() -> Int {
return queue.sync {
internalState
}
}
}


🟠objc_sync_enter / objc_sync_exit
Эти функции используются для синхронизации в Objective-C и могут быть использованы в Swift.
class ThreadSafeClass: NSObject {
private var internalState = 0

func increment() {
objc_sync_enter(self)
internalState += 1
objc_sync_exit(self)
}

func getState() -> Int {
objc_sync_enter(self)
let state = internalState
objc_sync_exit(self)
return state
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое Hashable?

Hashable — это протокол, позволяющий объектам быть хэшируемыми для использования в структурах данных, таких как Set или Dictionary. Он требует реализации метода hash(into:).

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1
🤔 Как работают выделения?

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

🚩Как работают

🟠Аллокация (выделение памяти)
Статическая аллокация: Память выделяется во время компиляции и существует на протяжении всего времени выполнения программы. Используется для глобальных и статических переменных.
int globalVar = 10; // Статическая память     


Стековая аллокация: Память выделяется при вызове функции и освобождается при выходе из функции. Используется для локальных переменных.
void function() {
int localVar = 20; // Стековая память
}


Куча (динамическая аллокация): Память выделяется по запросу во время выполнения программы и освобождается вручную (в языках с ручным управлением памятью) или автоматически (в языках с автоматическим управлением памятью, например, через сборщик мусора).
int *ptr = (int*)malloc(sizeof(int) * 10); // Выделение памяти в куче
free(ptr); // Освобождение памяти


🟠Деаллокация (освобождение памяти)
Вручную: Программист отвечает за освобождение памяти, выделенной в куче.
free(ptr);     


Автоматически: Сборщик мусора (Garbage Collector) автоматически освобождает память, которая больше не используется.
// В Java нет необходимости освобождать память вручную.     


🚩Примеры

C/C++ (ручное управление памятью):
#include <stdio.h>
#include <stdlib.h>

int main() {
int *arr = (int*)malloc(sizeof(int) * 5); // Выделение памяти
if (arr == NULL) {
// Ошибка выделения памяти
return 1;
}
// Использование массива
for (int i = 0; i < 5; i++) {
arr[i] = i;
}
// Освобождение памяти
free(arr);
return 0;
}


Python (автоматическое управление памятью):
def create_list():
my_list = [i for i in range(5)] # Выделение памяти автоматически
return my_list # Память освобождается автоматически, когда объект больше не используется

my_list = create_list()
print(my_list)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1🤔1