LINUX.ORG.RU

Можно, используя переопределение операторов new/delete.

E ★★★
()

И не забыть явно вызвать декструктор.

Shadow1251
()

Как-то так?

#include <iostream>

class A {
public:
  int a;
  A() : a(10) { std::cout << "A::A()\n"; };
};

int main() {
  char *data = (char*)malloc(1000);
  A *pA = new (data+100) A();
  std::cout << pA->a << "\n";
}

invy ★★★★★
()
Последнее исправление: invy (всего исправлений: 1)
Ответ на: комментарий от g0t0

Коротко сможешь описать юзкейс где тебе это понадобилось и без этого ну никак не обойтись?

Гемдев. Много аллокаций мелких (и не очень) объектов каждый фрейм.

andreyu ★★★★★
()
Ответ на: комментарий от g0t0

В виртуальных машинах по типу JVM и deathNOTE вполне уместная идея, чтобы потребление памяти не росло как на дрожжах.

Shadow1251
()
Ответ на: комментарий от next_time

вот я и не уловил, почему?

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

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

Т.е. ты хочешь сказать что портянка:

uint8_t *buffer = ...;
Obj *obj = new (buffer) Obj();
...
obj->~Obj();
buffer_free(buffer);
Нагляднее чем:
Obj *obj = new Obj();
delete obj;
?

Где переопределенный new у Obj размещает его в пуле. Ясно-понятно. Вспомнишь мои слова когда все то что ты наваяешь придется отлаживать и поддерживать.

NegatiV
()
Ответ на: комментарий от NegatiV

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

Shadow1251
()
Ответ на: комментарий от Shadow1251

Ну смотри, есть два логически эквивалентных куска кода, но один из них короче и соответствует идиоме используемого ЯП. Более того, короткая версия семантически нагляднее, т.к. реализуемая логика(создание/удаление объекта) соответствует идиоме ЯП, а все специфические манипуляции с памятью скрыты «под капотом».

NegatiV
()
Ответ на: комментарий от Shadow1251

И да, как в этом случае передавать владение созданным объектом другим модулям программы? Вот создал я с помощью placement new объект и должен передать его в модули которые поработают с ним, а потом сами удаляют. Как быть?

NegatiV
()
Ответ на: комментарий от NegatiV

Предполагаю, т.к. не копался, что испольование placemet new имеет смысл в реализации контейнеров встроенных и полиморфных типов.
Например контейнер std::vector. Если вспомнить, то std::vector имеет две функции-члена:

size_type size() const;
и
size_type capacity() const;
Первая возвращает количество объектов уже находящихся в контейнере, тогда как вторая возвращает количество возможных размещений в области памяти, которая была выделена заранее. Причем вторая величина может быть больше или равна первой. Таким образом, в момент создания непустого контейнера std::vector выделяется некоторая область памяти, способная вместить в себя не только запрошенное количество объектов, но и + N (величина N зависит от реализации и может быть и std::vector::size() * 2). После вызова push_back() указатель на последний элемент в котейнере сравнивается с указателем на место последнего возможного размещения и если место еще есть, вызывается placement new, который без выделения памяти, инициализирует эту область и вызывает конструктор обекта. Если же указатели равны, то вызывается аллокатор, для выделения места, необходимого под новое количество объектов + N.

Суть в том, что контроль над размещением осуществляет объект контейнера и тем объектам, которые будут в нем хранится не нужно перегружать для себя new/delete и new[]/delete[].

Shadow1251
()
Ответ на: комментарий от NegatiV

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

А что касается переопределения new/delete и new[]/delete[] в базовом классе - это не снимает проблему расшаривания между объектами иерархии самого пула.

Shadow1251
()
Ответ на: комментарий от NegatiV

Да и судя по последним веяниям моды юзать надо

std::scoped_allocator_adaptor
:)

Shadow1251
()

Сплюсплюс - РАК!

#include <stdio.h>
#include <stdlib.h>

struct A
{
  int i;
};

void init_a(struct A *p, int i)
{
  p->i =i;
}

void deinit_a(struct A *p)
{
  p->i =0;
}

int main()
{
  struct A *p = &(struct A){}; //antitsar combo!
  init_a(p, 1);
  printf("%d\n", p->i);
  deinit_a(p);
  init_a(p, 2);
  printf("%d\n", p->i);
  deinit_a(p);
  //free(p);
  return 0;
}

nanoolinux ★★★★
()
Ответ на: комментарий от Shadow1251

Все верно, placement new нужен для управления объектами произвольного типа. Так как пул объектов (а именно этого хочет ТС) — это обычно обобщенная реализация, перегруженные операторы не помогут ну никак.

staseg ★★★★★
()
Ответ на: комментарий от andreyu

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

next_time ★★★★★
()
Ответ на: комментарий от Selat

А какой профит аллокатору от знания выравнивания?

Аллокатору может профита и нет, а вот скорость при обращении к объекту возрастает прилично.

andreyu ★★★★★
()
Ответ на: комментарий от NegatiV

Нагляднее чем:

Хочу сказать, что тут явно видно, что память выделяется в пуле.

Где переопределенный new у Obj размещает его в пуле. Ясно-понятно.

А вот тут не ясно, где выделяется память. Все делается неявно.

Вспомнишь мои слова когда все то что ты наваяешь придется отлаживать и поддерживать.

Ну ок.

andreyu ★★★★★
()
Ответ на: комментарий от vzzo

А деструкторов у объектов нет?

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

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

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

next_time ★★★★★
()
Ответ на: комментарий от next_time

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

Использование своего аллокатора - это оверхед? Тогда у меня для вас плохие новости.

andreyu ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.