Почему std :: make_shared не может скомпилироваться для типа с удаленным оператором new? - PullRequest
4 голосов
/ 18 января 2020

Я пытаюсь написать запрещенный тип кучи, т. Е. Тип, который нельзя построить на выделенной памяти кучи. После удаления оператора new и размещения new я думал, что достигну этого. Но создание общего указателя с использованием std::make_shared все еще компилируется.

Почему std::make_shared<A>() не удается скомпилировать при удалении новых операторов?

#include <memory>

class A {
public:
    void* operator new(size_t) = delete;
    void* operator new(size_t, void*) = delete;
    void* operator new [] (size_t) = delete;
};

// Regular new fails
A* a1 = new A();

// Placement new fails
void* pv = std::malloc(sizeof(A));
A* a2 = new (pv) A();

// make_shared works
std::shared_ptr<A> a3 = std::make_shared<A>();

1 Ответ

6 голосов
/ 18 января 2020

std::make_shared указано в единицах ::​new (pv) T(std​::​forward<Args>(args)...).

[util.smartptr.shared.create]

2 Эффекты : выделяет память, подходящую для объекта типа T, и создает объект в этой памяти посредством размещения нового выражения ::​new (pv) T(std​::​forward<Args>(args)...). Шаблон allocate_shared использует копию a для выделения памяти. Если выдается исключение, функции не действуют.

Распределенная память обычно предназначена для блока управления, а не напрямую new T. Затем объект создается с помощью размещения new, но новое выражение полностью квалифицировано для использования глобального размещения operator new вместо любых классов, определенных c.

[expr.new]

9 Если выражение new начинается с унарного оператора ​::, распределение имя функции ищется в глобальной области видимости. В противном случае, если выделенный тип является типом класса T или его массивом, имя функции распределения ищется в области действия T. Если при этом поиске не удается найти имя или если выделенный тип не является типом класса, распределение Имя функции ищется в глобальной области видимости.

Эти два использования полностью обойдут пользовательские удаленные операторы.

...