Какое использование используется для «нового размещения»?

Кто-нибудь здесь когда-нибудь использовал 9X_cpp "новое размещение" C++? Если да, то зачем? Мне 9X_new кажется, что это будет полезно только на 9X_cpp оборудовании с отображением памяти.

502
5

  • @ Andrei-NiculaePetre На самом деле, я считаю [пример] (https://en.wikipedia.org/w/index.php?title=C%2B%2B11&oldid=869582471#Unrestricted_unions) в статье в Википедии довольно плохим, так как просто предполагает, что предшествующе ...
23
Общее количество ответов: 23

Ответ #1

Ответ на вопрос: Какое использование используется для «нового размещения»?

Новое размещение позволяет вам создать объект в уже выделенной памяти.

Вы можете сделать это для оптимизации, когда 9X_memory-usage вам нужно создать несколько экземпляров 9X_memory-deallocation объекта, и быстрее не перераспределять память 9X_operator-new каждый раз, когда вам нужен новый экземпляр. Вместо 9X_cxx этого может быть более эффективным выполнить 9X_new-operator одно выделение для блока памяти, который 9X_new может содержать несколько объектов, даже 9X_new-operator если вы не хотите использовать все сразу.

DevX 9X_memory-deallocation дает good example:

Стандартный C++ также поддерживает 9X_memory-deallocation размещение новый оператор, который создает объект 9X_memory-usage в предварительно выделенном буфере. Этот полезно 9X_cxx при создании пула памяти, сборщик мусора 9X_placement-new или просто когда производительность и безопасность 9X_memory-usage исключений первостепенное значение (нет 9X_memory-allocation опасности сбой выделения, так как память уже 9X_memory-deallocation выделено, и строительство объекта на предварительно 9X_placement-new выделенный буфер занимает меньше времени):

char *buf = new char[sizeof(string)]; // pre-allocated buffer string *p = new (buf) string("hi"); // placement new string *q = new string("hi"); // ordinary heap allocation 

Вы 9X_cpp также можете убедиться, что не может быть 9X_new сбоя выделения в определенной части критического 9X_memory-usage кода (например, в коде, выполняемом кардиостимулятором). В 9X_memory-usage этом случае вы захотите выделить память 9X_operator-new раньше, а затем использовать новое размещение 9X_operator-new в критическом разделе.

Распределение в месте размещения новое

Не следует освобождать 9X_memory-usage каждый объект, использующий буфер памяти. Вместо 9X_memory-allocation этого вы должны удалить [] только исходный 9X_c++ буфер. Затем вам придется вызывать деструкторы 9X_memory-usage ваших классов вручную. Хорошее предложение 9X_memory-usage по этому поводу можно найти в разделе часто 9X_placement-new задаваемых вопросов Страуструпа: Is there a "placement delete"?

443
10

  • Использование строки в качестве примера - худшее, что вы можете сделать, потому что существует мысленный конфликт между людьми, чтобы понять объект управления строкой и последовательность байтов, составляющих содержимое строки (ко ...

Ответ #2

Ответ на вопрос: Какое использование используется для «нового размещения»?

Мы используем его с настраиваемыми пулами 9X_operator-new памяти. Просто набросок:

class Pool { public: Pool() { /* implementation details irrelevant */ }; virtual ~Pool() { /* ditto */ }; virtual void *allocate(size_t); virtual void deallocate(void *); static Pool::misc_pool() { return misc_pool_p; /* global MiscPool for general use */ } }; class ClusterPool : public Pool { /* ... */ }; class FastPool : public Pool { /* ... */ }; class MapPool : public Pool { /* ... */ }; class MiscPool : public Pool { /* ... */ }; // elsewhere... void *pnew_new(size_t size) { return Pool::misc_pool()->allocate(size); } void *pnew_new(size_t size, Pool *pool_p) { if (!pool_p) { return Pool::misc_pool()->allocate(size); } else { return pool_p->allocate(size); } } void pnew_delete(void *p) { Pool *hp = Pool::find_pool(p); // note: if p == 0, then Pool::find_pool(p) will return 0. if (hp) { hp->deallocate(p); } } // elsewhere... class Obj { public: // misc ctors, dtors, etc. // just a sampling of new/del operators void *operator new(size_t s) { return pnew_new(s); } void *operator new(size_t s, Pool *hp) { return pnew_new(s, hp); } void operator delete(void *dp) { pnew_delete(dp); } void operator delete(void *dp, Pool*) { pnew_delete(dp); } void *operator new[](size_t s) { return pnew_new(s); } void *operator new[](size_t s, Pool* hp) { return pnew_new(s, hp); } void operator delete[](void *dp) { pnew_delete(dp); } void operator delete[](void *dp, Pool*) { pnew_delete(dp); } }; // elsewhere... ClusterPool *cp = new ClusterPool(arg1, arg2, ...); Obj *new_obj = new (cp) Obj(arg_a, arg_b, ...); 

Теперь вы можете 9X_memory-deallocation кластеризовать объекты вместе на одной арене 9X_memory-allocation памяти, выбрать распределитель, который 9X_cpp работает очень быстро, но не освобождает, использовать 9X_memory-management отображение памяти и любую другую семантику, которую 9X_placement-new вы хотите наложить, выбрав пул и передав 9X_new-operator его в качестве аргумента в новый оператор 9X_memory-deallocation размещения объекта.

72
3

  • @jdkoftinoff есть ли у вас ссылка на реал ...

Ответ #3

Ответ на вопрос: Какое использование используется для «нового размещения»?

Это полезно, если вы хотите отделить выделение 9X_memory-allocation памяти от инициализации. STL использует 9X_placement-new новое размещение для создания контейнерных 9X_cpp элементов.

57
0

Ответ #4

Ответ на вопрос: Какое использование используется для «нового размещения»?

Я использовал его в программировании в реальном 9X_new времени. Обычно мы не хотим выполнять какое-либо 9X_operator-new динамическое выделение (или освобождение) после 9X_c++ запуска системы, потому что нет гарантии, сколько 9X_memory-allocation времени это займет.

Что я могу сделать, так 9X_memory-allocation это предварительно выделить большой кусок 9X_new памяти (достаточно большой, чтобы вместить 9X_cxx любое количество того, что может потребоваться 9X_memory-deallocation классу). Затем, когда я выясню во время 9X_new выполнения, как создавать объекты, новое 9X_placement-new размещение можно использовать для создания 9X_cxx объектов именно там, где я хочу. Одна из 9X_memory-management ситуаций, в которой я использовал его, заключалась 9X_cpp в том, чтобы помочь создать разнородный 9X_c++ circular buffer.

Это, конечно, не для слабонервных, но именно 9X_c++ поэтому они делают его синтаксис корявым.

44
1

  • Что ж, реальный гетерогенный код с кольцевым буфером был действительно сложной задаче ...

Ответ #5

Ответ на вопрос: Какое использование используется для «нового размещения»?

Я использовал его для создания объектов, размещенных 9X_memory-management в стеке с помощью alloca().

Бесстыдная вилка: я писал об этом 9X_memory-management в блоге here.

27
1

  • @Ferruccio Это довольно круто, я заметил, что ваш макрос немного небезопасен, а именно размер может быть выражением. Если, например, передается x + 1, вы должны расширить его до sizeof (type) * x + 1, что было бы неверно. Вам нуж ...

Ответ #6

Ответ на вопрос: Какое использование используется для «нового размещения»?

Компьютерщик: БИНГО! Вы получили это полностью 9X_memory-management - это именно то, для чего он идеально подходит. Во 9X_memory-management многих встроенных средах внешние ограничения 9X_memory-allocation и / или общий сценарий использования вынуждают 9X_memory-management программиста отделить выделение объекта 9X_memory-usage от его инициализации. В совокупности C++ называет 9X_memory-usage это «созданием экземпляра»; но всякий раз, когда 9X_c++ действие конструктора должно быть вызвано 9X_cxx явно БЕЗ динамического или автоматического 9X_operator-new выделения, размещение new - это способ сделать 9X_operator-new это. Это также идеальный способ найти глобальный 9X_memory-allocation объект C++, который привязан к адресу аппаратного 9X_cpp компонента (ввод-вывод с отображением памяти) или 9X_new для любого статического объекта, который 9X_memory-usage по какой-либо причине должен находиться 9X_operator-new по фиксированному адресу.

14
0

Ответ #7

Ответ на вопрос: Какое использование используется для «нового размещения»?

Я использовал его для создания класса Variant 9X_memory-management (т. е. объекта, который может представлять 9X_cxx одно значение, которое может быть одним 9X_placement-new из нескольких различных типов).

Если все 9X_placement-new типы значений, поддерживаемые классом Variant, являются 9X_memory-deallocation типами POD (например, int, float, double, bool), тогда 9X_memory-deallocation объединение в стиле C с тегами достаточно, но 9X_cpp если вы хотите, чтобы некоторые типы значений 9X_new-operator были Для объектов C++ (например, std :: string) функция 9X_memory-usage объединения C не работает, поскольку типы 9X_new-operator данных, не относящиеся к POD, не могут быть 9X_memory-deallocation объявлены как часть объединения.

Вместо этого 9X_memory-deallocation я выделяю массив байтов достаточно большого 9X_memory-deallocation размера (например, sizeof (the_largest_data_type_I_support)) и 9X_memory-allocation использую размещение new для инициализации 9X_cpp соответствующего объекта C++ в этой области, когда 9X_memory-usage Variant настроен на хранение значения этого 9X_memory-deallocation типа. (И, конечно же, удаление места размещения 9X_new при переключении с другого типа данных, не 9X_memory-allocation относящихся к POD)

13
2

  • Эмм, типы данных, не относящиеся к POD, ** могут ** быть объявлены в объединении, если вы предоставите объединение ctor - и эй - этот ctor _, вероятно, будет использо ...

Ответ #8

Ответ на вопрос: Какое использование используется для «нового размещения»?

На самом деле это отчасти требуется для 9X_new-operator реализации любой структуры данных, которая 9X_memory-management выделяет больше памяти, чем минимально требуется 9X_c++ для количества вставленных элементов (т. е. что-либо, кроме 9X_new-operator связанной структуры, которая выделяет по 9X_memory-usage одному узлу за раз).

Возьмите такие контейнеры, как 9X_memory-allocation unordered_map, vector или deque. Все они выделяют больше памяти, чем 9X_cxx минимально требуется для элементов, которые 9X_cxx вы вставили до сих пор, чтобы не требовать 9X_c++ выделения кучи для каждой отдельной вставки. Давайте 9X_memory-usage использовать vector в качестве простейшего примера.

Когда 9X_cpp вы это сделаете:

vector vec; // Allocate memory for a thousand Foos: vec.reserve(1000); 

... из этого не получается 9X_operator-new тысяча Фу. Он просто выделяет / резервирует 9X_memory-management для них память. Если vector не использовал новое 9X_memory-allocation размещение здесь, он будет создавать Foos по 9X_memory-usage умолчанию повсюду, а также вызывать их деструкторы 9X_memory-usage даже для элементов, которые вы даже не вставляли.

Распределение! = Строительство, Освобождение! = Разрушение

Вообще 9X_memory-allocation говоря, для реализации многих структур данных, подобных 9X_c++ приведенным выше, нельзя рассматривать выделение 9X_memory-deallocation памяти и создание элементов как одну неделимую 9X_cpp вещь, а также нельзя рассматривать освобождение 9X_memory-management памяти и уничтожение элементов как одну 9X_placement-new неделимую вещь.

Между этими идеями должно 9X_new-operator быть разделение, чтобы избежать излишнего 9X_memory-deallocation вызова конструкторов и деструкторов слева 9X_memory-management и справа, и поэтому стандартная библиотека 9X_c++ разделяет идею std::allocator (которая не создает и не 9X_memory-allocation уничтожает элементы при размещении / освобождает 9X_placement-new память *) от контейнеров, которые ее используют, которые 9X_new создают элементы вручную, используя размещение 9X_memory-deallocation new, и вручную уничтожают элементы, используя 9X_memory-management явные вызовы деструкторов.

  • Я ненавижу дизайн std::allocator, но это уже другая тема, о которой я не буду разглагольствовать. :-D

В любом случае, я 9X_operator-new часто использую его, так как я написал ряд 9X_new универсальных, совместимых со стандартом 9X_cxx контейнеров C++, которые нельзя было построить 9X_cxx на основе существующих. Среди них - небольшая 9X_operator-new векторная реализация, которую я построил 9X_placement-new пару десятилетий назад, чтобы избежать выделения 9X_c++ кучи в общих случаях, и дерево-дерево с 9X_memory-usage эффективным использованием памяти (не выделяет 9X_memory-management по одному узлу за раз). В обоих случаях 9X_cpp я не мог реализовать их, используя существующие 9X_memory-management контейнеры, поэтому мне пришлось использовать 9X_new-operator placement new, чтобы избежать излишнего вызова конструкторов 9X_c++ и деструкторов для ненужных вещей слева 9X_cpp и справа.

Естественно, если вы когда-либо 9X_c++ работали с настраиваемыми распределителями 9X_placement-new для индивидуального распределения объектов, например, со 9X_cxx свободным списком, вы также обычно хотели 9X_new-operator бы использовать placement new, как этот (базовый пример, который 9X_memory-usage не беспокоит безопасность исключений или 9X_new-operator RAII ):

Foo* foo = new(free_list.allocate()) Foo(...); ... foo->~Foo(); free_list.free(foo); 

13
0

Ответ #9

Ответ на вопрос: Какое использование используется для «нового размещения»?

Размещение new также очень полезно при сериализации 9X_cxx (например, с boost :: serialization). За 9X_cpp 10 лет использования C++ это только второй 9X_new-operator случай, когда мне понадобилось новое размещение 9X_new (третий, если вы включите интервью :)).

10
0

Ответ #10

Ответ на вопрос: Какое использование используется для «нового размещения»?

Это полезно, если вы создаете ядро ​​- где 9X_operator-new вы размещаете код ядра, который вы читаете 9X_memory-usage с диска, или из таблицы? Вам нужно знать, куда 9X_cxx перейти.

Или в других, очень редких обстоятельствах, например, когда 9X_cpp у вас много выделенного места и вы хотите 9X_operator-new разместить несколько структур друг за другом. Их 9X_memory-usage можно упаковать таким образом без использования 9X_memory-usage оператора offsetof(). Однако для этого есть 9X_memory-deallocation и другие уловки.

Я также считаю, что некоторые 9X_memory-usage реализации STL используют размещение new, например 9X_memory-deallocation std :: vector. Таким образом они выделяют 9X_new-operator место для 2 ^ n элементов, и их не нужно 9X_memory-deallocation всегда перераспределять.

9
1

  • Операционная система, с которой я изучал основы ...

Ответ #11

Ответ на вопрос: Какое использование используется для «нового размещения»?

Это также полезно, когда вы хотите повторно 9X_placement-new инициализировать глобальные или статически 9X_placement-new распределенные структуры.

Старый способ C 9X_memory-allocation использовал memset() для установки всех элементов 9X_new-operator в 0. Вы не можете сделать это в C++ из-за 9X_cpp vtables и пользовательских конструкторов 9X_new-operator объектов.

Поэтому я иногда использую следующие

 static Mystruct m; for(...) { // re-initialize the structure. Note the use of placement new // and the extra parenthesis after Mystruct to force initialization. new (&m) Mystruct(); // do-some work that modifies m's content. } 

9
2

  • Разве вам не нужно было бы произвести соответствующее уничтожение перед повторной инициализацией таким ...

Ответ #12

Ответ на вопрос: Какое использование используется для «нового размещения»?

Я думаю, что это не было подчеркнуто ни 9X_c++ в одном ответе, но еще один хороший пример 9X_operator-new и использование для нового размещения - уменьшить фрагментацию 9X_placement-new памяти (за счет использования пулов памяти). Это 9X_memory-deallocation особенно полезно во встроенных системах 9X_memory-management и системах высокой доступности. В последнем 9X_placement-new случае это особенно важно, потому что для 9X_memory-allocation системы, которая должна работать 24/365 9X_new дней, очень важно не иметь фрагментации. Эта 9X_memory-deallocation проблема не имеет ничего общего с утечкой 9X_memory-usage памяти.

Даже когда используется очень хорошая 9X_operator-new реализация malloc (или аналогичная функция 9X_c++ управления памятью), очень трудно долго 9X_cxx иметь дело с фрагментацией. В какой-то момент, если 9X_new-operator вы не будете грамотно управлять вызовами 9X_memory-allocation резервирования / освобождения памяти, вы 9X_operator-new можете получить много небольших пропусков, которые трудно повторно 9X_cpp использовать (назначить новым резервированием). Итак, одним 9X_memory-allocation из решений, которые используются в этом 9X_memory-management случае, является использование пула памяти 9X_cpp для предварительного выделения памяти для 9X_operator-new объектов приложения. После каждого случая, когда 9X_cxx вам нужна память для какого-либо объекта, вы 9X_placement-new просто используете новое размещение для создания нового 9X_operator-new объекта в уже зарезервированной памяти.

Таким 9X_memory-usage образом, после запуска вашего приложения 9X_c++ вся необходимая память уже зарезервирована. Все 9X_placement-new новое резервирование / освобождение памяти 9X_memory-allocation идет в выделенные пулы (у вас может быть 9X_cxx несколько пулов, по одному для каждого класса 9X_operator-new объектов). В этом случае не происходит фрагментации 9X_new-operator памяти, так как не будет пропусков, и ваша 9X_memory-usage система может работать очень долгие периоды 9X_cpp (годы), не страдая от фрагментации.

Я видел 9X_memory-management это на практике специально для VxWorks RTOS, поскольку 9X_memory-usage ее система распределения памяти по умолчанию 9X_memory-deallocation сильно страдает от фрагментации. Таким образом, выделение 9X_operator-new памяти стандартным методом new / malloc 9X_memory-allocation в проекте было в основном запрещено. Вся 9X_memory-allocation зарезервированная память должна поступать 9X_memory-allocation в выделенный пул памяти.

9
0

Ответ #13

Ответ на вопрос: Какое использование используется для «нового размещения»?

Я использовал его для хранения объектов 9X_cxx с файлами с отображением памяти.
Конкретным 9X_placement-new примером была база данных изображений, которая 9X_memory-deallocation обрабатывала очень большое количество больших 9X_new изображений (больше, чем могло поместиться 9X_c++ в памяти).

8
0

Ответ #14

Ответ на вопрос: Какое использование используется для «нового размещения»?

Он используется std::vector<>, потому что std::vector<> обычно выделяет 9X_memory-management больше памяти, чем objects в vector<>.

8
0

Ответ #15

Ответ на вопрос: Какое использование используется для «нового размещения»?

Я использовал его для создания объектов 9X_cpp на основе памяти, содержащей сообщения, полученные 9X_memory-management из сети.

7
0

Ответ #16

Ответ на вопрос: Какое использование используется для «нового размещения»?

Я видел, как он использовался как slight performance hack for a "dynamic type" pointer (в разделе 9X_memory-deallocation «Под капотом»):

Но вот хитрый трюк, который 9X_placement-new я использовал, чтобы получить быструю производительность 9X_memory-allocation для небольших типов: если сохраняемое значение 9X_cpp может поместиться внутри void *, я на самом 9X_placement-new деле не утруждаю себя выделением нового 9X_memory-allocation объекта, я заставляю его в самом указателе 9X_c++ с использованием нового размещения

7
0

Ответ #17

Ответ на вопрос: Какое использование используется для «нового размещения»?

Как правило, новое размещение используется 9X_placement-new для того, чтобы избавиться от затрат на 9X_placement-new размещение «нормального нового».

Другой сценарий, в 9X_new-operator котором я его использовал, - это место, где 9X_cxx я хотел получить доступ к указателю на объект, который 9X_memory-usage еще должен был быть построен, для реализации 9X_memory-allocation синглтона для каждого документа.

5
0

Ответ #18

Ответ на вопрос: Какое использование используется для «нового размещения»?

Это может быть удобно при использовании 9X_cpp общей памяти, среди прочего ... Например: http://www.boost.org/doc/libs/1_51_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.conditions.conditions_anonymous_example

5
0

Ответ #19

Ответ на вопрос: Какое использование используется для «нового размещения»?

Единственное место, с которым я столкнулся, - это 9X_new-operator контейнеры, которые выделяют непрерывный 9X_operator-new буфер, а затем заполняют его объектами по 9X_new мере необходимости. Как уже упоминалось, std 9X_memory-management :: vector может делать это, и я знаю, что 9X_operator-new некоторые версии MFC CArray и / или CList 9X_cxx сделали это (потому что именно там я впервые 9X_new-operator столкнулся с этим). Метод перераспределения 9X_memory-allocation буфера - очень полезная оптимизация, и размещение 9X_cpp new в значительной степени является единственным 9X_memory-management способом создания объектов в этом сценарии. Он 9X_c++ также иногда используется для создания объектов 9X_memory-deallocation в блоках памяти, выделенных вне вашего прямого 9X_placement-new кода.

Я использовал его в аналогичном качестве, хотя 9X_operator-new это случается нечасто. Однако это полезный 9X_cpp инструмент для набора инструментов C++.

4
0

Ответ #20

Ответ на вопрос: Какое использование используется для «нового размещения»?

Механизмы сценариев могут использовать его 9X_memory-allocation в собственном интерфейсе для выделения собственных 9X_memory-management объектов из сценариев. См. Примеры в Angelscript 9X_memory-allocation (www.angelcode.com/angelscript).

4
0

Ответ #21

Ответ на вопрос: Какое использование используется для «нового размещения»?

См. файл fp.h в проекте xll по адресу http://xll.codeplex.com. Он 9X_memory-deallocation решает проблему «неоправданной дружбы с 9X_cxx компилятором» для массивов, которые любят 9X_memory-usage переносить свои размеры с собой.

typedef struct _FP { unsigned short int rows; unsigned short int columns; double array[1]; /* Actually, array[rows][columns] */ } FP; 

3
0

Ответ #22

Ответ на вопрос: Какое использование используется для «нового размещения»?

Вот убийственное использование встроенного 9X_memory-management конструктора C++: выравнивание по строке 9X_memory-management кэша, а также другие степени двойки границ. Вот 9X_operator-new my ultra-fast pointer alignment algorithm to any power of 2 boundaries with 5 or less single-cycle instructions:

/* Quickly aligns the given pointer to a power of two boundary IN BYTES. @return An aligned pointer of typename T. @brief Algorithm is a 2's compliment trick that works by masking off the desired number in 2's compliment and adding them to the pointer. @param pointer The pointer to align. @param boundary_byte_count The boundary byte count that must be an even power of 2. @warning Function does not check if the boundary is a power of 2! */ template inline T* AlignUp(void* pointer, uintptr_t boundary_byte_count) { uintptr_t value = reinterpret_cast(pointer); value += (((~value) + 1) & (boundary_byte_count - 1)); return reinterpret_cast(value); } struct Foo { Foo () {} }; char buffer[sizeof (Foo) + 64]; Foo* foo = new (AlignUp (buffer, 64)) Foo (); 

Разве это не вызовет у вас улыбку (:-). Я 9X_operator-new ♥♥♥ C++ 1x

3
0

Ответ #23

Ответ на вопрос: Какое использование используется для «нового размещения»?

У меня тоже есть идея. В C++ есть zero-overhead principle. Но исключения 9X_c++ не следуют этому принципу, поэтому иногда 9X_memory-management они отключаются переключателем компилятора.

Давайте 9X_placement-new посмотрим на этот пример:

#include #include #include int main() { struct A { A() { printf("A()\n"); } ~A() { printf("~A()\n"); } char data[1000000000000000000] = {}; // some very big number }; try { A *result = new A(); printf("new passed: %p\n", result); delete result; } catch (std::bad_alloc) { printf("new failed\n"); } } 

Мы размещаем здесь 9X_memory-management большую структуру, проверяем, успешно ли 9X_memory-usage выделено, и удаляем ее.

Но если у нас отключены 9X_memory-allocation исключения, мы не сможем использовать блок 9X_cpp try и не сможем обработать новый [] сбой.

Итак, как 9X_placement-new мы можем это сделать? Вот как:

#include #include #include int main() { struct A { A() { printf("A()\n"); } ~A() { printf("~A()\n"); } char data[1000000000000000000] = {}; // some very big number }; void *buf = malloc(sizeof(A)); if (buf != nullptr) { A *result = new(buf) A(); printf("new passed: %p\n", result); result->~A(); free(result); } else { printf("new failed\n"); } } 
  • Используйте простой malloc.
  • Проверить, не удалось ли выполнить C
  • В случае успеха мы используем новое размещение
  • Вызов деструктора вручную (мы не можем просто вызвать удаление)
  • звонок бесплатный, так как мы вызвали malloc

UPD @Useless написал 9X_new комментарий, который открыл мне, что существует 9X_placement-new new(nothrow), который следует использовать в этом случае, но 9X_c++ не метод, который я написал ранее. Пожалуйста, не 9X_memory-deallocation используйте код, который я написал ранее. Извините.

1
2

  • Конечно, вы могли бы просто использовать ...