Начиная с C++11, из-за нескольких причин, разработчики стремятся использовать классы смарт-указатель для динамических объектов жизни. И с этих новых классов интеллектуальных указателей, стандарты, даже рекомендовать не использовать операторы, такие как новый
вместо этого они предлагают использовать make_shared В " или " make_unique, чтобы избежать некоторых ошибок.
Если мы хотим использовать смарт-указатель класса, как shared_ptr
, мы можем построить один, как,
shared_ptr<int> p(new int(12));
Также мы хотели бы передать пользовательским deleter на занятия смарт-указатель,
shared_ptr<int> p(new int(12), deleter);
С другой стороны, если мы хотим использовать make_shared в выделять, напр. инт
, вместо того, чтобы использовать новые
и `shared_ptr конструктор, как на первом выше выражение, мы можем использовать
auto ip = make_shared<int>(12);
Но что, если мы хотим также передать пользовательским deleter к make_shared в
, есть правильный способ сделать это? Похоже, составители, по крайней мере на GCC, выдает ошибку,
auto ip = make_shared<int>(12, deleter);
Как другие сказали, make_shared в
не может быть использован с пользовательским deleter. Но я хочу объяснить, почему.
Существует обычай deleters, потому что вы выделили курсором в какой-то особый путь, и поэтому вы должны быть в состоянии освободить ее, соответственно, особый путь. Ну, make_shared в` выделяет указатель с "новой". Объекты, выделенные с "новой", должна быть освобождена с "удалить". Какой стандарт Нижнего послушно делает.
Короче говоря, если вы можете жить с поведением кластера по умолчанию, вы можете жить с дефолтом освобождение поведение тоже. И если вы можете'т жить с поведением кластера по умолчанию, вы должны использовать allocate_shared
, который использует предоставленный распределителя как выделять и освобождать память.
Кроме того, make_shared в
разрешено (и почти наверняка) выделить память для T
и блок управления для shared_ptr в то же распределение. Это то, что ваш делетер может'т действительно знаю о или заниматься. В то время как allocate_shared
способен работать, поскольку распределителя вы предоставляете можете сделать выделение и освобождение обязанностей.
Как и в документации, make_shared в
принимает список аргументов, с которым экземпляр Т будет построен*.<БР/>
Кроме того, в документации сказано, что:
эта функция обычно используется, чтобы заменить конструкции с std::shared_ptr и л;т>(Т(аргументы...)) общий указатель на исходный указатель, возвращаемый вызовом нового.
Из-за этого, можно сделать вывод, что вы можете'т установить пользовательский Стиратель.<БР/> Чтобы сделать это, вы должны создать shared_ptr для себя посредством права конструктор&.ЛТ;БР/> В качестве примера конструктор из предлагаемого списка, вы можете использовать:
template< class Y, class Deleter >
shared_ptr( Y* ptr, Deleter d );
Таким образом, код будет что-то вроде:
auto ptr = std::shared_ptr(new MyClass{arg1, arg2}, myDeleter);
Вместо:
auto ptr = std::make_shared<MyClass>(arg1, arg2);
Вы можете'т. make_shared в<П>
направляет аргументы в конструктор типа "Т". Он используется для простого случая, когда вы хотите делетер по умолчанию.
Это является неуказанным, как make_shared вполучает памяти для объекта (его может использовать оператор new или функции malloc
или какой-то распределитель) так что нет никакого способа пользовательским deleter мог знать, как поступить правильно. make_shared в
создает объект, так что вы должны также полагаться на нее, чтобы уничтожить объект правильно и делать соответствующие убирать, что бы это ни было.
также мы хотели бы передать пользовательским deleter на занятия смарт-указатель,
shared_ptr и Л;int> п(новый инт(12), делетер);
Я не'т считаю, что это очень реалистичный пример. Пользовательским deleter обычно используется, когда ресурс был получен каким-то особым образом. Если вы только что создали с "новым", как это, то зачем тебе пользовательским deleter в любом случае?
Если вы просто хотите, чтобы некоторый код будет работать на уничтожение затем положить его в деструктор! Таким образом, вы также можете использовать его с make_shared в
например
struct RunSomethingOnDestruction {
RunSomethingOnDestruction(int n) : i(n) { }
~RunSomethingOnDestruction() { /* something */ }
int i;
};
auto px = std::make_shared<RunSomethingOnDestruction>(12);
std:shared_ptr<int> p(px, px->i);
Это дает вам shared_ptr и Л;int>
, созданный make_shared в
(так что вы получите оптимизаций памяти сделано make_shared в
), Что может запустить пользовательский код на уничтожение.
Если вы используете пользовательским deleter вы можете'т использовать make_unique или
make_shared в функции при создании объектов смарт-указатель . Поскольку мы должны предоставить нашим пользовательским deleter эти функции не поддерживают это .
Дон'т использовать make_unique или make_shared в Если вам нужна пользовательским deleter или применяя исходный указатель из других стран.
По идее если вам нужен специализированный способ удалить ваш объект, вы, вероятно, нужно особым образом, чтобы создать их .
Пусть говорят, что мы тест класс
#include <iostream>
using namespace std;
class Test
{
private :
int data;
public :
Test() :data{0}
{
cout << "Test constructor (" << data << ")" << endl;
}
Test(int d) : data{ d }
{
cout << "Test constructor (" << data << ")" << endl;
}
int get_data() const { return data; }
~Test()
{
cout << "Test Destructor (" << data << ')' << endl;
}
};
// main function.
int main()
{
// It's fine if you use make_shared and custom deleter like this
std::shared_ptr<Test> ptr(new Test{1000},
[](Test *ptr)
{
cout << "some Code that you want to execute ";
delete ptr;
});
return 0;
}
Но если использовать make_shared в функции, вы получите ошибку компилятора
std::shared_ptr<Test> ptr = make_shared<Test>(1000,
[](Test *ptr){
cout << "some Code that you want to execute ";
delete ptr;
});
Функцию make_shared в основном является оболочкой для новых
и удалить
и если вы хотите пользовательским deleter вы должны обеспечить вам нужную "новый" и "удалить"