Безопасно ли копировать класс в неинициализированную память? - PullRequest
0 голосов
/ 30 апреля 2018

Я должен использовать malloc для выделения памяти. У меня есть пользовательский класс, которому нужен пользовательский operator=. Допустим, это A:

class A {
public:
  int n;
  A(int n) : n(n) {}
  A& operator=(const A& other) {
   n = other.n;
   return *this;
  }
};

Я выделяю память с malloc:

int main() {
   A* a = (A*) malloc(sizeof(A));
   A b(1);

   //Is it safe to do this as long as I copy everything in operator=?
   *a = b;

   //Clean up
   a->~A();
   free(a);
   return 0;
}

Я знаю, что могу также использовать новое место размещения:

a = new (a) A(b);

Безопасно ли копировать пользовательский класс в неинициализированную память?

Спасибо

Ответы [ 3 ]

0 голосов
/ 30 апреля 2018

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

0 голосов
/ 30 апреля 2018

Как уже отвечено, назначение копирования (или любой функции-члена) на несуществующий объект не в порядке.

Помимо размещения new, вы могли бы вместо этого вызвать std::uninitialized_copy_n или std::uninitialized_copy (что сделает внутреннее построение размещения. Это удобно, когда вам нужно скопировать-создать несколько объектов в неинициализированную память. Пример для вашего единственного объекта:

std::uninitialized_copy_n(&b, 1, a);
0 голосов
/ 30 апреля 2018

Размещение нового правильно

использование A& operator=(const A& other) с не сконструированным "this" неверно (представьте, что если у вас есть нетривиальный тип, например std::string внутри A, то воздействие должно уничтожить неинициализированную строку, прежде чем повлиять на новое значение).

Как только вы сделаете новое размещение, вы можете использовать назначение.

auto p = new (a) A;
*p = b; // ok
...