我测试了C ++ 11 shared_ptr,并感到惊讶 在这个例子中
#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <exception>
using namespace std;
class MyExc
{
};
class Slot
{
public:
Slot(const std::string &str = "NONAME") : m_name(str)
{
cout << "Constructor of slot: " << m_name << endl;
}
virtual ~Slot()
{
cout << "Destructor of slot: " << m_name << endl;
}
void sayName()
{
cout << "Slot name is: " << m_name << endl;
// throw MyExc();
}
private:
string m_name;
};
void testShared(shared_ptr<Slot> & m_share)
{
m_share->sayName();
}
int main()
{
vector<shared_ptr<Slot>> vec {make_shared<Slot>("0"), make_shared<Slot>("1"), make_shared<Slot>("2"), make_shared<Slot>("3"), make_shared<Slot>("4")};
for (auto& x:vec)
testShared(x);
return 0;
}
我看到了正确的输出
插槽构造函数:0
插槽构造:1
插槽构造:2
插槽构造:3
插槽构造:4
插槽名称为:0
插槽名称是:1
插槽名称是:2
插槽名称是:3
插槽名称是:4
槽的析构函数:0
槽的析构函数:1
槽的析构函数:2
槽的析构函数:3
插槽的析构函数:4
但如果我取消注释行
throw MyExc();
输出已更改,析构函数调用消息未显示
在抛出&#39; MyExc&#39;的实例后终止调用
插槽构造:0
插槽构造:1
插槽构造:2
插槽构造:3
插槽构造:4
插槽名称为:0
这是否意味着内存泄漏?
答案 0 :(得分:1)
在你的情况下,是的,有一个内存泄漏(不是很重要,因为程序将立即终止,操作系统将回收内存)。
为了实现这一点,您需要注意堆栈展开(即,在调用堆栈时销毁局部变量)仅由标准保证,如果异常被捕获。如果异常永远不会被捕获并直接进入std::terminate
,无论是否发生展开都取决于编译器和&amp;标准库。
引用C ++ 11:
15.2:
1当控件从 throw-expression 传递给处理程序时,将为所有自动对象调用析构函数 从输入try块开始构造。自动对象以相反的顺序销毁 完成他们的建设。
3为从try块到a的路径构造的自动对象调用析构函数的过程 throw-expression 被称为“堆栈展开。” ...
15.3:
9如果未找到匹配的处理程序,则调用函数
std::terminate()
;是否堆栈 在对std::terminate()
的调用之前解开是实现定义的(15.5.1)。