重置 std::shared_ptr 会导致重置其删除器吗?
Does resetting std::shared_ptr lead to resetting its deleter?
也许我误解了c++中智能指针的某些方面,但是执行这段代码后:
class cls
{
public:
class deleter
{
public:
const cls& obj;
deleter(const cls& c) : obj(c) {}
void operator()(int* num)
{
std::cout << "deleter was called" << std::endl;
if (num)
{
std::cout << "num in deleter: " << *num << std::endl;
if (*num == *obj.int_ptr)
{
std::cout << "equal " << *num << " = " << *obj.int_ptr << std::endl;
delete num;
}
else
std::cout << "not equal" << std::endl;
}
}
};
std::shared_ptr<int> int_ptr;
cls() : int_ptr(nullptr,deleter(*this)) {}
};
int main()
{
cls obj;
obj.int_ptr.reset(new int{15});
return 0;
}
输出:
deleter was called
0
我注意到 shared_ptr 中的 reset() 删除了在其构造函数中传递给它的自定义删除器。相反 unique_ptr 没有表现出这种行为,这对我来说很奇怪。
那么这是怎么回事?
删除器在 std::shared_ptr 中的存储方式与在 std::unique_ptr 中的存储方式不同。 std::unique_ptr 使用空基优化 (EBO) 来存储删除器,这意味着 std::unique_ptr 继承了删除器。 std::shared_ptr 不会这样做,这就是为什么两者之间的删除器 API 不同的原因。
std::shared_ptr
将删除器存储在控制块中。因此,您可以切换删除器并始终将 std::shared_ptr
与多种删除器一起使用,同时与指向相同数据的 std::shared_ptr
的所有其他实例共享它。
std::unique_ptr
不需要任何类型的东西,必要时将删除器存储在它的实例中。您还必须将 deleter 的用法指定为模板参数之一。
基本上,在 std::shared_ptr
中,删除器是数据的一部分,在 std::unique_ptr
中,删除器是 class.
的一部分
当我们给nullptr
赋值或者在std::shared_ptr上调用reset时,会在清理内存后清除指针和getdeleter。 unique_ptr 的处理方式不同。
下面是库中的函数,它减少 shared_ptr 的计数,如果 reference_count 为零,则继续销毁:
void _Decref() noexcept { // decrement use count
if (_MT_DECR(_Uses) == 0) {
_Destroy();
_Decwref();
}
}
因此,一旦您重置并且引用 _count 为零,那么 shared_ptr 自定义删除器将因重置而被删除。
也许我误解了c++中智能指针的某些方面,但是执行这段代码后:
class cls
{
public:
class deleter
{
public:
const cls& obj;
deleter(const cls& c) : obj(c) {}
void operator()(int* num)
{
std::cout << "deleter was called" << std::endl;
if (num)
{
std::cout << "num in deleter: " << *num << std::endl;
if (*num == *obj.int_ptr)
{
std::cout << "equal " << *num << " = " << *obj.int_ptr << std::endl;
delete num;
}
else
std::cout << "not equal" << std::endl;
}
}
};
std::shared_ptr<int> int_ptr;
cls() : int_ptr(nullptr,deleter(*this)) {}
};
int main()
{
cls obj;
obj.int_ptr.reset(new int{15});
return 0;
}
输出:
deleter was called
0
我注意到 shared_ptr 中的 reset() 删除了在其构造函数中传递给它的自定义删除器。相反 unique_ptr 没有表现出这种行为,这对我来说很奇怪。
那么这是怎么回事?
删除器在 std::shared_ptr 中的存储方式与在 std::unique_ptr 中的存储方式不同。 std::unique_ptr 使用空基优化 (EBO) 来存储删除器,这意味着 std::unique_ptr 继承了删除器。 std::shared_ptr 不会这样做,这就是为什么两者之间的删除器 API 不同的原因。
std::shared_ptr
将删除器存储在控制块中。因此,您可以切换删除器并始终将 std::shared_ptr
与多种删除器一起使用,同时与指向相同数据的 std::shared_ptr
的所有其他实例共享它。
std::unique_ptr
不需要任何类型的东西,必要时将删除器存储在它的实例中。您还必须将 deleter 的用法指定为模板参数之一。
基本上,在 std::shared_ptr
中,删除器是数据的一部分,在 std::unique_ptr
中,删除器是 class.
当我们给nullptr
赋值或者在std::shared_ptr上调用reset时,会在清理内存后清除指针和getdeleter。 unique_ptr 的处理方式不同。
下面是库中的函数,它减少 shared_ptr 的计数,如果 reference_count 为零,则继续销毁:
void _Decref() noexcept { // decrement use count
if (_MT_DECR(_Uses) == 0) {
_Destroy();
_Decwref();
}
}
因此,一旦您重置并且引用 _count 为零,那么 shared_ptr 自定义删除器将因重置而被删除。