如何将删除器传递给 make_shared?
How to pass deleter to make_shared?
自 C++11 以来,由于多种原因,开发人员倾向于将智能指针 classes 用于动态生命周期对象。对于那些新的智能指针 classes,标准,甚至建议不要使用像 new
这样的运算符,而是建议使用 make_shared
或 make_unique
来避免一些容易出错的操作。
如果我们喜欢使用智能指针class,比如shared_ptr
,我们可以构造一个,比如
shared_ptr<int> p(new int(12));
我们还想将自定义删除器传递给智能指针 classes,
shared_ptr<int> p(new int(12), deleter);
另一方面,如果我们喜欢使用 make_shared
来分配,例如。 int
,而不是使用 new
和 shared_ptr
构造函数,就像上面的第一个表达式一样,我们可以使用
auto ip = make_shared<int>(12);
但是如果我们还想将自定义删除器传递给 make_shared
,有什么正确的方法吗?似乎编译器,至少是 gcc,给出了一个错误,
auto ip = make_shared<int>(12, deleter);
你不能。 make_shared<T>
将提供的参数转发给 T
类型的构造函数。当您需要默认删除器时,它用于简单的情况。
从 documentation 开始,make_shared
接受一个 参数列表,用于构造 T 的实例。
此外,文档说:
This function is typically used to replace the construction std::shared_ptr(new T(args...)) of a shared pointer from the raw pointer returned by a call to new.
因此,您可以推断出您无法设置自定义 删除器。
为此,您必须通过右 constructor.
为自己创建 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
。用 new
分配的对象应该用 delete
释放。标准删除器尽职尽责。
简而言之,如果您可以接受默认的分配行为,那么您也可以接受默认的 解除分配 行为。如果您不能接受默认的分配行为,您应该使用 allocate_shared
,它使用提供的分配器来分配和释放存储。
此外,make_shared
被允许(并且几乎肯定会)在同一个分配中为 T
分配内存和为 shared_ptr 分配控制块。这是您的删除者无法真正了解或处理的事情。而 allocate_shared
能够处理它,因为您提供的分配器可以执行分配和释放任务。
未指定 make_shared
如何获取对象的内存(它可以使用 operator new
或 malloc
或某种分配器)因此自定义删除器无法知道如何做正确的事。 make_shared
创建对象,因此您还必须依靠它来正确销毁对象并进行适当的清理,无论是什么。
Also we would like to pass a custom deleter to smart pointer classes,
shared_ptr<int> p(new int(12), deleter);
我认为这不是一个很现实的例子。当以某种特殊方式获取资源时,通常会使用自定义删除器。如果您只是像这样使用 new
创建它,那么为什么您仍然需要自定义删除器?
如果您只想让一些代码在销毁时 运行 就把它放在析构函数中!这样您仍然可以将它与 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);
这为您提供了一个由 make_shared
创建的 shared_ptr<int>
(因此您可以通过 make_shared
完成内存优化),它将 运行 一些自定义代码销毁.
如果您使用自定义删除器,则在创建智能指针对象时不能使用 make_unique
或 make_shared
函数。由于我们需要提供自定义删除器,因此这些功能不支持。
如果您需要自定义删除器或采用来自其他地方的原始指针,请不要使用 make_unique 或 make_shared。
我们的想法是,如果您需要一种专门的方法来删除您的对象,您可能也需要一种专门的方法来创建它们。
假设我们class测试
#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 函数是 new
和 delete
的包装器,如果您想要自定义删除器,您必须提供自己的 new
和 delete
自 C++11 以来,由于多种原因,开发人员倾向于将智能指针 classes 用于动态生命周期对象。对于那些新的智能指针 classes,标准,甚至建议不要使用像 new
这样的运算符,而是建议使用 make_shared
或 make_unique
来避免一些容易出错的操作。
如果我们喜欢使用智能指针class,比如shared_ptr
,我们可以构造一个,比如
shared_ptr<int> p(new int(12));
我们还想将自定义删除器传递给智能指针 classes,
shared_ptr<int> p(new int(12), deleter);
另一方面,如果我们喜欢使用 make_shared
来分配,例如。 int
,而不是使用 new
和 shared_ptr
构造函数,就像上面的第一个表达式一样,我们可以使用
auto ip = make_shared<int>(12);
但是如果我们还想将自定义删除器传递给 make_shared
,有什么正确的方法吗?似乎编译器,至少是 gcc,给出了一个错误,
auto ip = make_shared<int>(12, deleter);
你不能。 make_shared<T>
将提供的参数转发给 T
类型的构造函数。当您需要默认删除器时,它用于简单的情况。
从 documentation 开始,make_shared
接受一个 参数列表,用于构造 T 的实例。
此外,文档说:
This function is typically used to replace the construction std::shared_ptr(new T(args...)) of a shared pointer from the raw pointer returned by a call to new.
因此,您可以推断出您无法设置自定义 删除器。
为此,您必须通过右 constructor.
为自己创建 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
。用 new
分配的对象应该用 delete
释放。标准删除器尽职尽责。
简而言之,如果您可以接受默认的分配行为,那么您也可以接受默认的 解除分配 行为。如果您不能接受默认的分配行为,您应该使用 allocate_shared
,它使用提供的分配器来分配和释放存储。
此外,make_shared
被允许(并且几乎肯定会)在同一个分配中为 T
分配内存和为 shared_ptr 分配控制块。这是您的删除者无法真正了解或处理的事情。而 allocate_shared
能够处理它,因为您提供的分配器可以执行分配和释放任务。
未指定 make_shared
如何获取对象的内存(它可以使用 operator new
或 malloc
或某种分配器)因此自定义删除器无法知道如何做正确的事。 make_shared
创建对象,因此您还必须依靠它来正确销毁对象并进行适当的清理,无论是什么。
Also we would like to pass a custom deleter to smart pointer classes,
shared_ptr<int> p(new int(12), deleter);
我认为这不是一个很现实的例子。当以某种特殊方式获取资源时,通常会使用自定义删除器。如果您只是像这样使用 new
创建它,那么为什么您仍然需要自定义删除器?
如果您只想让一些代码在销毁时 运行 就把它放在析构函数中!这样您仍然可以将它与 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);
这为您提供了一个由 make_shared
创建的 shared_ptr<int>
(因此您可以通过 make_shared
完成内存优化),它将 运行 一些自定义代码销毁.
如果您使用自定义删除器,则在创建智能指针对象时不能使用 make_unique
或 make_shared
函数。由于我们需要提供自定义删除器,因此这些功能不支持。
如果您需要自定义删除器或采用来自其他地方的原始指针,请不要使用 make_unique 或 make_shared。
我们的想法是,如果您需要一种专门的方法来删除您的对象,您可能也需要一种专门的方法来创建它们。
假设我们class测试
#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 函数是 new
和 delete
的包装器,如果您想要自定义删除器,您必须提供自己的 new
和 delete