C++成员变量的new操作应该放在构造函数中吗?
来源:互联网 发布:linux 看网站访问ip 编辑:程序博客网 时间:2024/06/06 04:23
C++类中的指针成员变量(生命期紧随该类)的new操作,应该在类的构造函数中?还是需要一个Init()函数,也就是在构造函数外?为了解决这个问题,写个例子测试下。。
首先定义三个类,没有什么重要意义
class A{public:A(){ std::cout << "A()" <<std::endl; }~A(){ std::cout << "~A()" <<std::endl; }};class B{public:B(){ std::cout << "B()" <<std::endl; }~B(){ std::cout << "~B()" <<std::endl; }};class C{public:C(){ std::cout << "C()" <<std::endl; }~C(){ std::cout << "~C()" <<std::endl; }};
现在抛出问题,下面两段代码,那种的处理方式比较好呢?
代码1:
class Test{public:Test(){a_ = new A;b_ = new B;c_ = new C;}~Test(){delete a_;delete b_;delete c_;}private:A* a_;B* b_;C* c_;};代码2:class Test{public:Test(){}void Init(){a_ = new A;b_ = new B;c_ = new C;}~Test(){delete a_;delete b_;delete c_;}private:A* a_;B* b_;C* c_;};对于上面的两个代码的调用如下:
//代码1执行如下:Test * test1 = new Test;delete test1;//代码2执行如下:Test * test2 = new Test;test2->Init();delete test2;
输出的结果都如下:
A()B()C()~A()~B()~C()到目前为止,好像并不能发现两段代码有什么不同之处! 但是别着急。
看看异常出现的时候(throw模拟异常),会有怎样的结果:看看以下这两个代码
代码1:
class Test{public:Test(){a_ = new A;b_ = new B;throw std::string("构造函数中抛出异常");c_ = new C;}~Test(){delete a_;delete b_;delete c_;}private:A* a_;B* b_;C* c_;};int main(int argc, char *argv[]) {Test * test = NULL;try {test = new Test;} catch (const std::string& str) {std::cout << str << std::endl;}delete test;std::cout << "main end" << std::endl;return 0;}输出结果:A()B()构造函数中抛出异常main end代码2:
class Test{public:Test(){}void Init(){a_ = new A;b_ = new B;throw std::string("Init()中抛出异常");c_ = new C;}~Test(){delete a_;delete b_;delete c_;}private:A* a_;B* b_;C* c_;};int main(int argc, char *argv[]) {Test * test = NULL;try {test = new Test;test->Init();} catch (const std::string& str) {std::cout << str << std::endl;}delete test;std::cout << "main end" << std::endl;return 0;}输出结果:A()B()Init()中抛出异常~A()~B()~C()new(4421,0x7fffd62833c0) malloc: *** error for object 0x7fffd6110010: pointer being freed was not allocated*** set a breakpoint in malloc_error_break to debug //小编注,错误原因是c_没有初始化,是一个随机数,delete会产生崩溃分析上面的例子,很明显可以发现:
代码1:调用了A、B的构造函数,但是没有调用A、B的析构函数,程序运行结束,造成了内存泄漏;
代码2:调用了A、B的构造函数,调用了A、B、C的析构函数。因为c_没有调用构造函数,却去析构它(此时c_是随机值),因此程序崩溃。
到了这里,你可能会觉得,那两种方式都有问题的,那该怎么写呢?? 但是,还是别着急,分析上面两个代码出错的原因,可以联想到delete NULL,是的,C++的delete兼容NULL,析构空并不会报错!!
所以上面的代码2可以修改成这样:
class Test{public:Test(){a_ = NULL;b_ = NULL;c_ = NULL;}void Init(){a_ = new A;b_ = new B;throw std::string("Init()中抛出异常");c_ = new C;}~Test(){delete a_;delete b_;delete c_;}private:A* a_;B* b_;C* c_;};int main(int argc, char *argv[]) {Test * test = NULL;try {test = new Test;test->Init();} catch (const std::string& str) {std::cout << str << std::endl;}delete test;std::cout << "main end" << std::endl;return 0;}输出结果如下:A()B()Init()中抛出异常~A()~B()main end
perfect!!!完美解决,没有内存泄漏,程序没有崩溃!!!
最后的最后,总结下,构造函数中尽量不要有new的操作,new的操作可以定义一个Init()来单独处理,代码如下:最后再试试上面的代码1,看能不能通过赋空解决呢?
class Test{public:Test(){a_ = NULL;b_ = NULL;c_ = NULL;a_ = new A;b_ = new B;throw std::string("构造函数中抛出异常");c_ = new C;}~Test(){delete a_;delete b_;delete c_;}private:A* a_;B* b_;C* c_;};int main(int argc, char *argv[]) {Test * test = NULL;try {test = new Test;} catch (const std::string& str) {std::cout << str << std::endl;}delete test;std::cout << "main end" << std::endl;return 0;}运行一下,还是老样子(内存泄漏),朽木不可雕也,抛弃!
class Test{public:Test(){a_ = NULL;b_ = NULL;c_ = NULL;}void Init(){a_ = new A;b_ = new B;c_ = new C;}~Test(){delete a_;delete b_;delete c_;}private:A* a_;B* b_;C* c_;};
阅读全文
0 0
- C++成员变量的new操作应该放在构造函数中吗?
- C++:在构造函数中使用new时应该注意的事项
- c++中什么类型的成员变量只能在构造函数的初始化列表中进行
- C++:在成员函数后面放const的作用
- TPtr类型的成员变量无法在构造函数中赋值的问题
- 在构造函数的参数化列表中调用基类构造函数初始化继承来的成员变量
- 在构造函数的参数化列表中调用基类构造函数初始化继承来的成员变量
- 没有默认构造函数的问题, 对于类成员变量有别的类成员,则在类 构造函数中也必须对那个类成员变量进行初始化,除非那个类 成员有默认构造函数
- 使用java反射操作类的构造函数,成员变量和成员方法
- 在成员函数中调用构造函数
- 在构造函数中使用new的注意事项
- JAVA反射中类的构造函数,成员变量,成员方法的使用
- C++中使用初始化列表比在构造函数中对成员变量赋值更高效
- 【C/C++】在一个类中重载另一个类的构造函数 ----构造函数是一个特殊的操作符
- [C#]父类与子类的静态成员变量、实例成员变量、构造函数的执行顺序
- [C#]父类与子类的静态成员变量、实例成员变量、构造函数的执行顺序
- [C++]父类与子类的静态成员变量、实例成员变量、构造函数的执行顺序
- (25)继承中成员变量、函数中覆盖、构造函数的理解
- Spring MVC 入门指南(二):@RequestMapping用法详解
- 1062. 最简分数(20)
- 回收站功能实现
- 某医药公司一台IBM x3850 RAID5数据丢失的恢复过程
- 一句话解释
- C++成员变量的new操作应该放在构造函数中吗?
- 解决GET方式请求中文乱码的几种方法
- httpClinent短信验证码
- Codeforces Round #430 (Div. 2)
- Servlet处理请求报文9
- 快速排序,排序一亿数据用时14秒
- Linux中启动Apache中的Could not reliably determine the server's fully qualified domain name问题
- 浅谈 python的类和对象
- 某安全浏览器竟然也被查出高危漏洞?开源安全问题不容忽视