Другие уже рассмотрели другие проблемы, поэтому я просто посмотрю на одну точку: вы когда-либо хотите вручную удалить объект.
Ответ да. @DavidSchwartz дал один пример, но это довольно необычный. Я приведу пример, который находится под капотом того, что много программистов на C++ все время используют: std::vector
(и std::deque
, хотя он не используется совсем так).
Как известно большинству людей, std::vector
выделяет больший блок памяти, когда/если вы добавляете больше предметов, чем может удерживать текущее распределение. Однако, когда он делает это, у него есть блок памяти, способный удерживать еще объектов, чем в данный момент в векторе.
Чтобы управлять этим, то, что делает vector
под чехлов выделяют сырец памяти через Allocator
объект (который, если не указано иное, означает, что он использует ::operator new
). Затем, когда вы используете (например) push_back
, чтобы добавить элемент в vector
, внутри вектора используется placement new
, чтобы создать элемент в (ранее) неиспользуемой части памяти.
Теперь, когда/если вы erase
товара из вектора? Он не может просто использовать delete
- это освободит весь блок памяти; он должен уничтожить один объект в этой памяти, не уничтожая других, или освобождая любой из блока памяти, который он контролирует (например, если вы erase
5 элементов из вектора, то сразу push_back
еще 5 предметов, это , гарантировал, что вектор будет не перераспределить память, когда вы делаете это.
Чтобы сделать это, вектор непосредственно уничтожает объекты в памяти явного вызова деструктора, не с помощью delete
.
Если, возможно, кто-то другой должен был написать контейнер, используя непрерывное хранилище примерно как vector
делает (или какой-то вариант этого, например, std::deque
действительно), вы почти наверняка захотите использовать ту же технику.
Только, например, рассмотрим, как вы можете написать код для циклического кольцевого буфера.
#ifndef CBUFFER_H_INC
#define CBUFFER_H_INC
template <class T>
class circular_buffer {
T *data;
unsigned read_pos;
unsigned write_pos;
unsigned in_use;
const unsigned capacity;
public:
circular_buffer(unsigned size) :
data((T *)operator new(size * sizeof(T))),
read_pos(0),
write_pos(0),
in_use(0),
capacity(size)
{}
void push(T const &t) {
// ensure there's room in buffer:
if (in_use == capacity)
pop();
// construct copy of object in-place into buffer
new(&data[write_pos++]) T(t);
// keep pointer in bounds.
write_pos %= capacity;
++in_use;
}
// return oldest object in queue:
T front() {
return data[read_pos];
}
// remove oldest object from queue:
void pop() {
// destroy the object:
data[read_pos++].~T();
// keep pointer in bounds.
read_pos %= capacity;
--in_use;
}
// release the buffer:
~circular_buffer() { operator delete(data); }
};
#endif
В отличие от стандартных контейнеров, это использует operator new
и operator delete
напрямую. Для реального использования вы, вероятно, хотите использовать класс распределителя, но на данный момент он будет больше отвлекаться, чем внести вклад (IMO, во всяком случае).
Даже ваши конкретные вопросы слишком широки. «Этот указатель позже удален» и «с учетом нового адреса, чтобы указать на», совершенно разные. Найдите больше (на некоторые из них ответили), а затем задайте отдельные вопросы для тех частей, которые вы не смогли найти. –