在具有自动存储持续时间的对象上使用智能指针
Posted
技术标签:
【中文标题】在具有自动存储持续时间的对象上使用智能指针【英文标题】:Using of Smart Pointers on objects with automatic storage duration 【发布时间】:2016-09-13 07:33:42 【问题描述】:如果我将智能指针(scoped_ptr
、unique_ptr
或 shared_ptr
)应用于具有自动存储持续时间(即存储在堆栈上)的对象,是否会出现问题?我假设不是在这两种情况下(有和没有智能指针),如果没有更多指针指向它们,它们将被删除。指针本身始终具有自动存储持续时间,即如果超出范围,它们将被删除。
【问题讨论】:
只要您还包含一个不删除对象的自定义删除器,您就可以... 【参考方案1】:是的,有一个问题(一个大问题):您正在使用智能指针来做某事(我不知道是什么),而它们并不是设计用来做的。它们旨在管理动态分配对象的生命周期。它们解决了从C
继承的问题,它们为需要动态分配/释放的对象提供所有权(它们不限于内存(指针);您实际上可以使用智能指针来管理需要获取/释放的任何类型的资源,例如系统资源、文件描述符等)。
好的,但是除了哲学问题,还有实际问题吗?
是的!!。智能指针会在拥有的对象上调用delete
/delete[]
,当指针不是分别从new
/new[]
获取时,即为Undefined Behavior。
是的,您可以使用一个什么都不做的自定义删除器,但是使用智能指针有什么意义呢?
【讨论】:
将 smart_ptr 与无操作删除器一起使用有什么意义?假设您有一个map<shared_ptr<X>, Y>
,由int X::id_
索引,因为大多数类逻辑都规定(甚至可能在您无法更改的库中)。现在,您要查找与某个 int id
值对应的 Y
。您可以做的是在堆栈上创建一个虚拟X
,并将密钥设置为您的id
(以及默认设置的其余部分)使用无操作删除器,执行搜索并开心(而不是迭代地图 - 甚至可能无法访问 - 或从堆中分配 X
)【参考方案2】:
这里是demo:
class Foo
public:
Foo()cout << "Foo created!\n";
~Foo()cout << "Foo destroyed!\n";
;
void go()
Foo foo;
cout << "Position A\n";
Foo foo1;
cout << "Position B\n";
Foo *foo2;
cout << "Position C\n";
Foo *foo3 = new Foo;
cout << "Position D\n";
std::shared_ptr<Foo> foo3(new Foo);
cout << "Position E\n";
std::shared_ptr<Foo> foo3(&foo);
cout << "Position F\n";
输出如下:
Foo created!
Position A
Foo created!
Foo destroyed!
Position B
Position C
Foo created!
Position D
Foo created!
Foo destroyed!
Position E
Foo destroyed!
以
结尾运行时错误: 错误:free():无效指针:0x00007ffda60f0e67
注意位置 D-E 和位置 E-F 之间的区别(删除不是来自 new 的指针,因此会导致 未定义的行为。
【讨论】:
请与我们分享您在哪里使用自定义的无操作删除器。【参考方案3】:是的,这是一个问题,因为智能指针将(暂时忽略自定义删除器)在不是通过 new
(即 UB)创建的对象上调用 delete
,并且析构函数将被调用两次(这会导致也有未定义的行为)。
顺便说一句。如果您尝试通过两个独立的智能指针管理对象,也会导致错误。
因此,就生命周期管理而言,“越多越好” 绝对不是真的。
【讨论】:
以上是关于在具有自动存储持续时间的对象上使用智能指针的主要内容,如果未能解决你的问题,请参考以下文章
C++编程经验:智能指针 -- 裸指针管得了的我要管,裸指针管不了的我更要管!