C++构造函数失败后,其对应的析构函数会被自动调用吗? 答案是不会。
能在构造函数中抛出异常,然后在外面捕获吗? 可以,但不建议这样做。C++之父和herb sutter这样的最顶级专家建议不要把容易出错的代码放在构造函数中,当然如果非要在构造函数做一些容易失败的事,那就在构造里throw异常吧。另外对于析构函数,Herb Sutter在Exceptional c++ 中也说过说:“永远都不要写能够抛出异常的析构函数” [1]。
所以综上,我们写代码时,还是最好不要把易出错的代码写在构造函数里了,我们加个init函数,构造成功后再init,与init对应的还要有个exit函数。
代码示例1:抛出异常后,delete将不不被执行,将造成内存泄漏。
#include <iostream> void remodel(std::string & str) std::string * ps = new std::string(str); if (true) throw "test exception"; str = *ps; delete ps; return; void main() remodel(std::string("abcde")); 智能指针和异常处理 我们可以使用智能指针和异常处理来防止内存泄漏。 #include <iostream> //[2] #include <string> #include <memory> class report private: std::string str; public: report(const std::string s) : str(s) { std::cout << "Object created.\n"; ~report() { std::cout << "Object deleted.\n"; void comment() const { std::cout << str << "\n"; throw "test exception"; int main() report *ps = NULL; ps = new report("using auto ptr"); ps->comment(); catch (...) std::cout << "test" << std::endl; if (ps) delete ps; ps = NULL; std::auto_ptr<report> ps(new report("using auto ptr")); ps->comment(); catch(...) std::cout << "test" << std::endl; #if 0 std::shared_ptr<report> ps(new report("using shared ptr")); ps->comment(); std::unique_ptr<report> ps(new report("using unique ptr")); ps->comment(); #endif return 0; [1] C++中构造函数是没有返回值的,那么该如何处理构造函数中可能的错误 [2] C++智能指针简单剖析 构造子类对象的时候,在进入子类构造函数之前会先调用父类的构造函数。 如果没有显式调用父类构造函数就会调用默认的父类构造函数。但是你的父类又没有默认构造函数所以自然会出错。 3。几种修改方法: a。父类中重载构造函数,一个有参数,一个没参数。 class a { a(int a, int b, int c); 上述代码中,parent有一个shared_ptr类型的成员指向孩子,而child也有一个shared_ptr类型的成员指向父亲。然后在创建孩子和父亲对象时也使用了智能指针c和p,随后将c和p分别又赋值给child的智能指针成员parent和parent的智能指针成员child。,weak_ptr的构造函数不会修改引用计数的值,从而不会对对象的内存进行管理,其类似一个普通指针,但是不会指向引用计数的共享内存,但是可以检测到所管理的对象是否已经被释放,从而避免非法访问。2.智能指针的内存泄漏如何解决? 什么函数都有可能失败,构造函数也不另外,比如new一个对象或空间不成功。当构造函数失败的时候,其实很多时候我们不想这个对象被继续生成,这个时候就可以在构造函数里面抛出异常。C++规定构造函数抛出异常之后,对象将不被创建,析构函数也不会被执行,但已经创建成功的部分(比如一个类成员变量)会被部分逆序析构,不会产生内存泄漏。但有些资源需要在抛出异常前自己清理掉,比如打开成功的一个文件,最好关闭掉再抛出异 C++ 构造函数的异常是一个比较难缠的问题,很多时候,我们可能不去考虑这些问题,如果被问到,有人可能会说使用RAII管理资源。 但你真的考虑过如果构造函数失败了,到底会发生什么吗,前面构造成功的成员、基类对象应该怎样回收? 最近在知乎上看到有人提到这个问题: http://www.zhihu.com/question/22889420 看了陈硕的回答,抱着怀疑的心态写代码加以验证。 ... 用C++写代码的时候总是避免不了处理错误,一般来说有两种方式,通过函数的返回值或者抛出异常。C语言的错误处理一律是通过函数的返回值来判断的,一般是返回0、NULL或者-1表示错误,或者直接返回错误代码,具体是哪种方式没有统一的规定,各种API也各有各的偏好。譬如fopen函数,当成功时返回文件指针,失败时返回NULL,而POSIX标准的open函数则在成功时返回0或者正数,失败时返回-1,然后需要 构造函数中抛出的异常 1、标准C++中定义构造函数是一个对象构建自己,分配所需资源的地 方,一旦构造函数执行完毕,则表明这个对象已经诞生了,有自己的行为和内部的运行状态,之后还有对象的消亡过程(析构函数的执行)。可谁能保证对象的构造 过程一定能成功呢?说不定系统当前的某个资源不够,导致对象不能完全构建好自己(人都有畸形儿,更何况别的呢?朋友们!是吧!),因此通过什么方法来表明 构造函数中可不可以抛出异常?当然可以。从语法上来说,是可以的;从实际情况来看,现在的软件系统日渐庞大和复杂,很难保证 Constructor 在执行过程中完全不发生一点异常。 那么,如果构造函数中抛出异常,会发生什么情况呢? 一、构造函数中抛出异常将导致对象的析构函数不被执行。 C++仅能 delete 被完全构造的对象(fully constructed ...
我们可以使用智能指针和异常处理来防止内存泄漏。
#include <iostream> //[2] #include <string> #include <memory> class report private: std::string str; public: report(const std::string s) : str(s) { std::cout << "Object created.\n"; ~report() { std::cout << "Object deleted.\n"; void comment() const { std::cout << str << "\n"; throw "test exception"; int main() report *ps = NULL; ps = new report("using auto ptr"); ps->comment(); catch (...) std::cout << "test" << std::endl; if (ps) delete ps; ps = NULL; std::auto_ptr<report> ps(new report("using auto ptr")); ps->comment(); catch(...) std::cout << "test" << std::endl; #if 0 std::shared_ptr<report> ps(new report("using shared ptr")); ps->comment(); std::unique_ptr<report> ps(new report("using unique ptr")); ps->comment(); #endif return 0; [1] C++中构造函数是没有返回值的,那么该如何处理构造函数中可能的错误 [2] C++智能指针简单剖析 构造子类对象的时候,在进入子类构造函数之前会先调用父类的构造函数。 如果没有显式调用父类构造函数就会调用默认的父类构造函数。但是你的父类又没有默认构造函数所以自然会出错。 3。几种修改方法: a。父类中重载构造函数,一个有参数,一个没参数。 class a { a(int a, int b, int c); 上述代码中,parent有一个shared_ptr类型的成员指向孩子,而child也有一个shared_ptr类型的成员指向父亲。然后在创建孩子和父亲对象时也使用了智能指针c和p,随后将c和p分别又赋值给child的智能指针成员parent和parent的智能指针成员child。,weak_ptr的构造函数不会修改引用计数的值,从而不会对对象的内存进行管理,其类似一个普通指针,但是不会指向引用计数的共享内存,但是可以检测到所管理的对象是否已经被释放,从而避免非法访问。2.智能指针的内存泄漏如何解决? 什么函数都有可能失败,构造函数也不另外,比如new一个对象或空间不成功。当构造函数失败的时候,其实很多时候我们不想这个对象被继续生成,这个时候就可以在构造函数里面抛出异常。C++规定构造函数抛出异常之后,对象将不被创建,析构函数也不会被执行,但已经创建成功的部分(比如一个类成员变量)会被部分逆序析构,不会产生内存泄漏。但有些资源需要在抛出异常前自己清理掉,比如打开成功的一个文件,最好关闭掉再抛出异 C++ 构造函数的异常是一个比较难缠的问题,很多时候,我们可能不去考虑这些问题,如果被问到,有人可能会说使用RAII管理资源。 但你真的考虑过如果构造函数失败了,到底会发生什么吗,前面构造成功的成员、基类对象应该怎样回收? 最近在知乎上看到有人提到这个问题: http://www.zhihu.com/question/22889420 看了陈硕的回答,抱着怀疑的心态写代码加以验证。 ... 用C++写代码的时候总是避免不了处理错误,一般来说有两种方式,通过函数的返回值或者抛出异常。C语言的错误处理一律是通过函数的返回值来判断的,一般是返回0、NULL或者-1表示错误,或者直接返回错误代码,具体是哪种方式没有统一的规定,各种API也各有各的偏好。譬如fopen函数,当成功时返回文件指针,失败时返回NULL,而POSIX标准的open函数则在成功时返回0或者正数,失败时返回-1,然后需要 构造函数中抛出的异常 1、标准C++中定义构造函数是一个对象构建自己,分配所需资源的地 方,一旦构造函数执行完毕,则表明这个对象已经诞生了,有自己的行为和内部的运行状态,之后还有对象的消亡过程(析构函数的执行)。可谁能保证对象的构造 过程一定能成功呢?说不定系统当前的某个资源不够,导致对象不能完全构建好自己(人都有畸形儿,更何况别的呢?朋友们!是吧!),因此通过什么方法来表明 构造函数中可不可以抛出异常?当然可以。从语法上来说,是可以的;从实际情况来看,现在的软件系统日渐庞大和复杂,很难保证 Constructor 在执行过程中完全不发生一点异常。 那么,如果构造函数中抛出异常,会发生什么情况呢? 一、构造函数中抛出异常将导致对象的析构函数不被执行。 C++仅能 delete 被完全构造的对象(fully constructed ...
#include <iostream> //[2] #include <string> #include <memory> class report private: std::string str; public: report(const std::string s) : str(s) { std::cout << "Object created.\n"; ~report() { std::cout << "Object deleted.\n"; void comment() const { std::cout << str << "\n"; throw "test exception"; int main() report *ps = NULL; ps = new report("using auto ptr"); ps->comment(); catch (...) std::cout << "test" << std::endl; if (ps) delete ps; ps = NULL; std::auto_ptr<report> ps(new report("using auto ptr")); ps->comment(); catch(...) std::cout << "test" << std::endl; #if 0 std::shared_ptr<report> ps(new report("using shared ptr")); ps->comment(); std::unique_ptr<report> ps(new report("using unique ptr")); ps->comment(); #endif return 0;
[1] C++中构造函数是没有返回值的,那么该如何处理构造函数中可能的错误 [2] C++智能指针简单剖析 构造子类对象的时候,在进入子类构造函数之前会先调用父类的构造函数。 如果没有显式调用父类构造函数就会调用默认的父类构造函数。但是你的父类又没有默认构造函数所以自然会出错。 3。几种修改方法: a。父类中重载构造函数,一个有参数,一个没参数。 class a { a(int a, int b, int c); 上述代码中,parent有一个shared_ptr类型的成员指向孩子,而child也有一个shared_ptr类型的成员指向父亲。然后在创建孩子和父亲对象时也使用了智能指针c和p,随后将c和p分别又赋值给child的智能指针成员parent和parent的智能指针成员child。,weak_ptr的构造函数不会修改引用计数的值,从而不会对对象的内存进行管理,其类似一个普通指针,但是不会指向引用计数的共享内存,但是可以检测到所管理的对象是否已经被释放,从而避免非法访问。2.智能指针的内存泄漏如何解决? 什么函数都有可能失败,构造函数也不另外,比如new一个对象或空间不成功。当构造函数失败的时候,其实很多时候我们不想这个对象被继续生成,这个时候就可以在构造函数里面抛出异常。C++规定构造函数抛出异常之后,对象将不被创建,析构函数也不会被执行,但已经创建成功的部分(比如一个类成员变量)会被部分逆序析构,不会产生内存泄漏。但有些资源需要在抛出异常前自己清理掉,比如打开成功的一个文件,最好关闭掉再抛出异 C++ 构造函数的异常是一个比较难缠的问题,很多时候,我们可能不去考虑这些问题,如果被问到,有人可能会说使用RAII管理资源。 但你真的考虑过如果构造函数失败了,到底会发生什么吗,前面构造成功的成员、基类对象应该怎样回收? 最近在知乎上看到有人提到这个问题: http://www.zhihu.com/question/22889420 看了陈硕的回答,抱着怀疑的心态写代码加以验证。 ... 用C++写代码的时候总是避免不了处理错误,一般来说有两种方式,通过函数的返回值或者抛出异常。C语言的错误处理一律是通过函数的返回值来判断的,一般是返回0、NULL或者-1表示错误,或者直接返回错误代码,具体是哪种方式没有统一的规定,各种API也各有各的偏好。譬如fopen函数,当成功时返回文件指针,失败时返回NULL,而POSIX标准的open函数则在成功时返回0或者正数,失败时返回-1,然后需要 构造函数中抛出的异常 1、标准C++中定义构造函数是一个对象构建自己,分配所需资源的地 方,一旦构造函数执行完毕,则表明这个对象已经诞生了,有自己的行为和内部的运行状态,之后还有对象的消亡过程(析构函数的执行)。可谁能保证对象的构造 过程一定能成功呢?说不定系统当前的某个资源不够,导致对象不能完全构建好自己(人都有畸形儿,更何况别的呢?朋友们!是吧!),因此通过什么方法来表明 构造函数中可不可以抛出异常?当然可以。从语法上来说,是可以的;从实际情况来看,现在的软件系统日渐庞大和复杂,很难保证 Constructor 在执行过程中完全不发生一点异常。 那么,如果构造函数中抛出异常,会发生什么情况呢? 一、构造函数中抛出异常将导致对象的析构函数不被执行。 C++仅能 delete 被完全构造的对象(fully constructed ...
[1] C++中构造函数是没有返回值的,那么该如何处理构造函数中可能的错误 [2] C++智能指针简单剖析