LINUX.ORG.RU

Инициализация памяти оператором new в c++

 , ,


0

2

Не могу разобраться, в каких случаях new НЕ инициализирует память. Для классов с конструкторами, понятно, вызывается конструктор, память инициализируется. Для простых типов, похоже, что нет. А для структур, например? Просто мне надо выделять память под прочитанные из файла данные и терять время на её инициализацию неохота. malloc - то, что нужно, но хотелось бы иметь возможность обмазываться синтаксическим сахаром, типа unique_ptr.


Ты Страуструпа хоть почитал бы.. new выделяет память под объект и выполняет функции из конструктора. Если у тебя конструктор пустой, то только под объект память и будет выделена.

Чего здесь непонятного-то?

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

Правильный вариант я выше написал. С моим вариантом ты можешь организовать отложенный вызов конструктора, если понадобится. Выделяешь память через глобальный ::operator new, а когда надо можешь дёрнуть конструктор с помощью placement new.

DELIRIUM ☆☆☆☆☆
()
Последнее исправление: DELIRIUM (всего исправлений: 1)
Ответ на: комментарий от JaM

Вы используете C или C++, так как нюансы имеются?
Если память выделили для хранения адреса, то однозначно лучше := nullptr.

Владимир

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

Впрочем речь о конструкторе …

Владимир

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

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

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от JaM

Можно ещё malloc использовать, а твоим смарт принтерам определить custom deleter.

DELIRIUM ☆☆☆☆☆
()

Не могу разобраться, в каких случаях new НЕ инициализирует память.

Надо использовать ::operator new(). Вот тут вроде неплохой пример.

Для простых типов, похоже, что нет.

Простые типы можно инициализировать с помощью обычного new, а можно и не инициализировать.

#include <iostream>

int main()
{
  int * a = new int;    // не инициализируется
  int * b = new int(1); // инициализируется
  int * c = new int{2}; // инициализируется
    
  std::cout << *a << '\n' << *b << '\n' << *c << std::endl;
  return 0;
}

А для структур, например?

Структуры в C++ это те же самые классы. Просто есть парочка небольших отличий. Эти самые отличия можно на изичах нагуглить.

malloc - то, что нужно, но хотелось бы иметь возможность обмазываться синтаксическим сахаром, типа unique_ptr.

Попробуй так:

#include <iostream>
#include <memory>

int main()
{
  std::unique_ptr<int[], decltype(&free)> up((int*)malloc(4 * sizeof(int)), free);
    
  for (int i = 0; i < 4; ++i)
  {
    up[i] = i * i;
    std::cout << up[i] << std::endl;
  }
    
  return 0;
}
Nibbler
()
Ответ на: комментарий от Nibbler

Про второй аргумент шаблона у unique_ptr я забыл. А вообще, какая практическая разница между ::operator new() и malloc?

JaM
() автор топика

Просто мне надо выделять память под прочитанные из файла данные и терять время на её инициализацию неохота.

если оценить время очистки памяти и чтения файла, то ты занят «оптимизационной» ерундой

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

Для простого копирования содержимого файла в память есть mmap. И нечего тут выдумывать хрень всякую!

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

То для простого. А когда у тебя HDF5 и возникают такие вопросы.

JaM
() автор топика
Ответ на: комментарий от Nibbler

С POD типами в классах не всё так просто и зависит от наличия или отсутствия скобок (()) в выражении new:

#include <algorithm>
#include <iostream>

struct S {
    int data;
    std::string s = "hi";
};

int
main(void)
{
    char *bufA = new char[100];
    std::fill(bufA, bufA + 100, 255);

    char *bufB = new char[100];
    std::fill(bufB, bufB + 100, 255);

    S *a = new(bufA) S;
    std::cout << "a: " << a->data << ", " << a->s << '\n';

    S *b = new(bufB) S();
    std::cout << "b: " << b->data << ", " << b->s << '\n';

    return 0;
}

Вывод:

a: -1, hi
b: 0, hi
xaizek ★★★★★
()
Ответ на: комментарий от xaizek

А причём тут скобки? Инициализатор прописан в структуре. Хоть со скобками, хоть без скобок, s в объекте будет «hi».

JaM
() автор топика
Ответ на: комментарий от Nibbler

А, всё, дошло про какие ты скобки говоришь и откуда разница.

JaM
() автор топика
Ответ на: комментарий от xaizek

То есть, так как при new int() область памяти инициализируется нулем, то и при new S() поле data будет инициализироваться нулем?

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

Почему-почему, потому что стандарт такой. Навводили инициализаторов, я половину и не помню.

JaM
() автор топика
Ответ на: комментарий от Nibbler

Я очень надеюсь, что такие особенности языка никто не использует. Кстати, а если написать конструктор S():s(«lo») {} то кто победит?

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

Я очень надеюсь, что такие особенности языка никто не использует.

Об этом обязательно спросят на собеседовании. И если не ответишь, то заклеймят ничтожеством и пообещают перезвонить.

S():s(«lo») {} то кто победит

Победит сильнейший )

Nibbler
()
Последнее исправление: Nibbler (всего исправлений: 2)
Ответ на: комментарий от Nibbler

Всё правильно. Раз пользователь завёл конструктор, то ему и заботиться об инициализации data.

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

Хоть кто-то по делу отписал. Автор, покажи бенчи, а?

ncuxer
()

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

https://timsong-cpp.github.io/cppwp/n4659/expr.new#18

A new-expression that creates an object of type T initializes that object as follows:
* If the new-initializer is omitted, the object is default-initialized ([dcl.init]). [ Note: If no initialization is performed, the object has an indeterminate value.  — end note ]
* Otherwise, the new-initializer is interpreted according to the initialization rules of [dcl.init] for direct-initialization.

Теперь открывай [dcl.init] и штудируй. Копипастить сюда я не буду.

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

В теории как раз есть: malloc выделяет из хипа, а new - из free store. По факту это одно и то же, но в теории вот такое различие.

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

В теории как раз есть: malloc выделяет из хипа, а new - из free store.

Про какую теорию ты толкуешь? Что здесь значит new — new из new-expression или operator new?

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

Ты не путаешь понятия перегрузки и переопределения?

https://timsong-cpp.github.io/cppwp/n4659/replacement.functions#3:

The program’s definitions are used instead of the default versions supplied by the implementation ([support.dynamic]). Such replacement occurs prior to program startup ([basic.def.odr], [basic.start]).

replacement — это перегрузка или переопределение?

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

Про какую теорию ты толкуешь? Что здесь значит new — new из new-expression или operator new?

Нагородили костылей.

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

Комментарий к отмеченному ответу читал?

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