C++11 为什么共享ptr不';发生异常时,不要调用指针的析构函数
我测试了C++11 shared_ptr,感到很惊讶 在这个例子中C++11 为什么共享ptr不';发生异常时,不要调用指针的析构函数,c++11,shared-ptr,C++11,Shared Ptr,我测试了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 &
#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;
}
输出已更改,并且未显示析构函数调用消息
在抛出“MyExc”实例后调用terminate
插槽的构造函数:0插槽的构造函数:1
插槽的构造函数:2
插槽的构造函数:3
插槽的构造函数:4
插槽名称为:0
这是否意味着内存泄漏被放置在这里?在您的情况下,是的,存在内存泄漏(这并不重要,因为程序将立即终止,操作系统将回收内存) 要消除这种情况,您需要知道,只有在捕获异常时,标准才能保证堆栈展开(即在调用堆栈上升时销毁局部变量)。如果从未捕获到异常并直接转到
std::terminate
,则是否展开取决于编译器和标准库
引用C++11:
15.2:
1当控件从抛出表达式传递到处理程序时,将为所有自动对象调用析构函数
自输入try块后构造。自动对象的销毁顺序与
完成他们的建设
3为从try块到try块的路径上构造的自动对象调用析构函数的过程
抛出表达式称为“堆栈展开”
15.3:
9如果没有找到匹配的处理程序,则调用函数std::terminate()
;不管堆栈是否为空
在对std::terminate()
的调用被定义为实现之前展开(15.5.1)
谢谢,如果我修改代码为:for(auto&x:vec){try{testShared(x);}catch(MyExc&ex){exit;}>所有工作正常,输出为:插槽构造函数:0插槽构造函数:1插槽构造函数:2插槽构造函数:3插槽构造函数:4插槽名称为:0插槽名称为:1插槽名称为:2插槽名称为:3插槽名称为:4插槽析构函数:0插槽析构函数:1插槽析构函数:2插槽析构函数:3 Dslot:4Perhaps的Esstructor值得一提的是它这样工作的一个原因:通常,如果异常未经处理,程序(或实际上是操作系统)会选择性地保存一个崩溃转储,允许开发人员在调试器中加载该崩溃转储并找出错误所在。这通常对最终用户并不重要(无论哪种方式,程序都崩溃了),如果不展开堆栈,就可以直接指向引发异常的位置,并且所有局部变量都保持不变,从而使调试对开发人员更加友好。
throw MyExc();