Рассмотрим следующий пример:
#include <iostream>
struct A {
int i;
A(int i)
{
this->i = i;
}
A &operator=(const A &a) = delete;
A(const A &a) = delete;
};
int main()
{
A a(1);
new(&a) A(5);
//a = A(7); // not allowed since = is deleted in A
std::cout << a.i << std::endl;
}
Это простой пример с использованием оператора размещения new. Поскольку конструктор копирования и оператор присваивания struct A
были удалены (по какой-либо причине), изменить объект, который хранится в переменной A a
, невозможно, за исключением передачи его адреса оператору размещения new.
Причины для этого могут быть связаны с тем, что struct A
содержит большие массивы (например, 100M записей), которые необходимо будет скопировать в операторе присваивания и в конструкторе копирования.
Первая часть вопросавращается вокруг "законности" этого подхода. Я нашел этот вопрос stackoverflow, принятый ответ на который говорит
, это совершенно законно. И бесполезно, потому что вы не можете использовать var [A a
в этом случае] для ссылки на состояние [объекта], который вы сохранили в нем после нового размещения. Любой такой доступ является неопределенным поведением. […] Ни при каких обстоятельствах вы не можете ссылаться на var после размещения new'd поверх него.
Почему это так? Я видел несколько других примеров для оператора размещения new, которые всегда похожи на
A a(1);
A *b = new(&a) A(2);
// Now use *b instead of a
Насколько я понимаю, не имеет значения, используется ли A a
или A *b
для доступа к объекту с момента размещенияnew заменяет объект по адресу A a
, который, конечно, равен A a
. То есть я бы ожидал, что всегда b == &a
. Возможно, ответ был недостаточно ясен, и это ограничение связано с константностью члена класса.
Вот еще один пример с той же идеей, однако на этот раз struct A
встроен в другой объект:
#include <iostream>
struct A {
int *p;
A(int i)
{
p = new int(i);
}
~A()
{
delete p;
}
A &operator=(const A &a) = delete;
A(const A &a) = delete;
};
struct B {
A a;
B(int i) : a(i)
{
}
void set(int i)
{
a.~A(); // Destroy the old object
new(&a) A(i);
}
};
int main()
{
B b(1);
b.set(2);
std::cout << *(b.a.i) << std::endl;
// This should print 2 and there should be no memory leaks
}
Вопрос в основном тот же с тем же рассуждением. Допустимо ли размещение новых на адрес &a
?