TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #608 5.02K
Все грани new
#опытным

Не каждый знает, что в плюсах new - это как медаль, только лучше. У медали 2 стороны, а у new целых 3!

Сейчас со всем разберемся.

То, что наиболее часто используется, называется new expression. Это выражение делает 2 вещи последовательно: пытается в начале выделить подходящий объем памяти, а потом пытается сконструировать либо один объект, либо массив объектов в уже аллоцированной памяти. Возвращает либо указатель на объект, либо указатель на начало массива.

Выглядит оно так:

 // creates dynamic object of type int with value equal to 42
int* p_triv = new int(42);
// created an array of 42 dynamic objects of type int with values equal to zero
int* p_triv_arr = new int[42];

struct String {std::string str};

// creates dynamic object of custom type String using aggregate initialization
String* p_obj = new String{"qwerty"};
// created an array of 5 dynamic objects of custom type String with default initialization
String* p_obj = new String[5];


Эта штука делает 2 дела одновременно. А что, если мне не нужно выполнять сразу 2 этапа? Что, если мне нужна только аллокация памяти?

За это отвечает operator new. Это оператор делает примерно то же самое, что и malloc. То есть выделяет кусок памяти заданного размера. Выражение new именно этот оператор и вызывает, когда ему нужно выделить память. Но его можно вызвать и как обычную функцию, а также перегружать для конкретного класса:

// class-specific allocation functions
struct X
{
static void* operator new(std::size_t count)
{
std::cout << "custom new for size " << count << '\n';
// explicit call to operator new
return ::operator new(count);
}
 
static void* operator new[](std::size_t count)
{
std::cout << "custom new[] for size " << count << '\n';
return ::operator new;
}
};
 
int main()
{
X* p1 = new X;
delete p1;
X* p2 = new X[10];
delete[] p2;
}


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

Для этого есть placement new. Это тот же самый new expression, только для этого есть свой синтаксис. Сразу после new в скобках вы передаете указатель на область памяти, достаточной для создания объекта.

alignas(T) unsigned char buf[sizeof(T)];
// after new in parentheses we specified location of future object
T* tptr = new(buf) T;
// You must manually call the object's destructor
tptr->~T();


В этом случае кстати вызывается специальная перегрузка operator new:

void* operator new  (std::size_t count, void* ptr);


Однако она не делает ничего полезного и просто возвращает второй аргумент наружу.

Вот так по разному в С++ можно использовать new. Главное - не запутаться!

Have a lot of sides. Stay cool.

#cppcore #memory
  • 👍 35
  • ❤ 18
  • 🔥 8
  • 🏆 3
  • ⚡ 1
More from @grokaemcpp
  1. Oct 14, 2026​​Что внутри std::condition_variable? #опытным Более менее все знакомы с примитивом синхро…
  2. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  3. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  4. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  5. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  6. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →