util.smartptr.shared.const / 9 в C ++ 11:
Эффекты: Создает объект shared_ptr, которому принадлежит объект p и средство удаления d. Второй и четвертый конструкторы должны использовать копию a для выделения памяти для внутреннего использования.
Второй и четвертый конструкторы имеют эти прототипы:
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template<class D, class A> shared_ptr(nullptr_t p, D d, A a);
В последнем проекте util.smartptr.shared.const / 10 эквивалентен для нашей цели:
Эффекты: Создает объект shared_ptr, которому принадлежит объект p и средство удаления d. Когда T не является типом массива, первый и второй конструкторы разрешают shared_from_this с p. Второй и четвертый конструкторы должны использовать копию a для выделения памяти для внутреннего использования. Если выдается исключение, вызывается d (p).
Таким образом, распределитель используется, если есть необходимость выделить его в выделенной памяти. На основании текущего стандарта и соответствующих отчетов о дефектах, распределение не является обязательным, но предполагается, что комитет.
Хотя интерфейс shared_ptr
допускает реализацию, в которой никогда не бывает блока управления и все shared_ptr
и weak_ptr
помещены в связанный список, такой реализации на практике не существует. Кроме того, формулировка была изменена, предполагая, например, что она use_count
является общей.
Средство удаления требуется только для перемещения конструктива. Таким образом, невозможно иметь несколько копий в shared_ptr
.
Можно представить реализацию, которая помещает удалитель в специально разработанный shared_ptr
и перемещает его, когда shared_ptr
удаляется особый . Хотя реализация кажется согласованной, это также странно, тем более что для подсчета использования может потребоваться контрольный блок (возможно, возможно, даже страннее сделать то же самое с подсчетом использования).
Соответствующие DR, которые я нашел: 545 , 575 , 2434 (которые подтверждают, что все реализации используют блок управления и, по-видимому, подразумевают, что многопоточность ограничивает его), 2802 (который требует, чтобы средство удаления перемещалось только конструктивно, и, таким образом, предотвращал реализацию, где удалитель копируется между несколькими shared_ptr
).
a
) для освобождения этой памяти. Что подразумевает некоторое хранение этой копииa
. Об этом нет информации в [util.smartptr.shared.dest].Из std :: shared_ptr имеем:
И из std :: allocate_shared мы получаем:
Так что похоже, что std :: allocate_shared должен выделять
deleter
вместе с вашимAlloc
.РЕДАКТИРОВАТЬ: И из
n4810
§20.11.3.6 Создание [util.smartptr.shared.create][Акцент все мое]
Таким образом, стандарт говорит, что
std::allocate_shared
следует использоватьAlloc
для блока управления.источник
n4810
и обновил ответ.make_shared
не о самих конструкторах. Тем не менее, я могу использовать член для небольших удалителей.Я считаю, что это не определено.
Вот спецификация соответствующих конструкторов: [util.smartptr.shared.const] / 10
Теперь моя интерпретация заключается в том, что когда реализации требуется память для внутреннего использования, она делает это с помощью
a
. Это не значит, что реализация должна использовать эту память для размещения всего. Например, предположим, что есть эта странная реализация:Использует ли эта реализация «копию
a
для выделения памяти для внутреннего использования»? Да, это так. Он никогда не выделяет память, кроме как с помощьюa
. Есть много проблем с этой наивной реализацией, но давайте скажем, что она переключается на использование распределителей во всех случаях, кроме самого простого случая, в которомshared_ptr
конструируется непосредственно из указателя и никогда не копируется, не перемещается и не ссылается иным образом, и других сложностей нет. Дело в том, что то, что мы не можем представить себе правильную реализацию, само по себе не доказывает, что она не может существовать теоретически. Я не говорю, что такая реализация действительно может быть найдена в реальном мире, просто что стандарт, похоже, не запрещает ее активно.источник
shared_ptr
для небольших типов выделяет память в стеке. И так не соответствует стандартным требованиямstd::move(__d)
и отступайте ,allocate
когда требуется копирование.