C++中以独立语句将new对象置入智能指针

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: C++中以独立语句将new对象置入智能指针

1.问题的引入


假设现在有个函数priority()来处理程序的优先级,另一个函数用来在某动态分配的Widget对象上进行某些带有优先权的处理。


1class Widget{
2    // ...
3};
4
5int priority();
6
7void processWidget(std::shared_ptr<Widget> pw, int priority);


现在,有下面的语句调用函数processWidget(),如下所示:


1processWidget(new Widget, priority());


上面的语句调用必然会导致编译器报错,这是由于std::shared_ptr构造函数需要一个原始指针,但该构造函数是一个explicit显式构造函数,无法进行隐式转换。下面调用方式将new Widget原始指针转换为processWidget()所要求的std::shared_ptr。,如下所示:


1processWidget(std::shared_ptr<Widget>(new Widget), priority());


重点来了:即使经过上面一系列的骚操作(即使用对象管理式资源),上面的调用也可能发生内存泄漏


2.内存泄漏发生的原因及解决方法



先看看编译器的工作原理。编译器在生成对processWidget()函数的调用之前,必须先解析其中的参数processWidget()函数接收两个参数,分别是智能指针的构造函数和整型的函数priority()。在调用智能指针构造函数之前,编译器必须先解析其中的new Widget语句。因此,解析该函数的参数分为三步:  

   (1).调用priority();

   (2).执行new Widget;
   (3).调用std::shared_ptr构造函数;


C+编译器以什么样的固定顺序去完成上面的这些事情呢?答案是未知。这和其他语言如Java和C#不同,这两种语言总是以固定的顺序完成函数参数的解析。但是,在C++中可以确定步骤(2)一定先于步骤(3)执行,因为new Widget还要被传递作为std::shared_ptr构造函数的一个实参。然而,对于priority()的调用可以在步骤(1)、步骤(2)、步骤(3)执行。假设编译器选择以步骤(2)执行它,最终的操作次序如下:  

(1).执行new Widget;    (2).调用priority();    (3).调用std::shared_ptr构造函数


但是,如果priority()函数抛出了异常呢?那么从new语句动态分配的资源在到达智能指针构造函数之前就已经泄露了。解决方法:使用一个单独的语句来创建智能指针对象。


1std::shared_ptr<Widget> pw(new Widget);  // 放在单独的语句中
2processWidget(pw, priority());   // 不会泄露资源


编译器是逐语句编译的,通过使用一个单独的语句来构造智能指针对象,编译器就不会随意改动解析顺序,保证了生成的机器代码顺序是异常安全的,以及这样的代码写出来也更加美观。


3.总结



(1) 以独立语句将new对象存储于智能指针内。如果不这样做,一旦异常被抛出,有可能导致难以察觉的内存泄漏。

相关文章
|
22天前
|
编译器 C++
C++之类与对象(完结撒花篇)(上)
C++之类与对象(完结撒花篇)(上)
32 0
|
10天前
|
存储 安全 编译器
在 C++中,引用和指针的区别
在C++中,引用和指针都是用于间接访问对象的工具,但它们有显著区别。引用是对象的别名,必须在定义时初始化且不可重新绑定;指针是一个变量,可以指向不同对象,也可为空。引用更安全,指针更灵活。
|
17天前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
20 4
|
17天前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
18 4
|
18天前
|
存储 编译器 C语言
【C++打怪之路Lv3】-- 类和对象(上)
【C++打怪之路Lv3】-- 类和对象(上)
15 0
|
22天前
|
编译器 C++ 数据库管理
C++之类与对象(完结撒花篇)(下)
C++之类与对象(完结撒花篇)(下)
28 0
|
22天前
|
编译器 C++
C++之类与对象(3)(下)
C++之类与对象(3)(下)
30 0
|
22天前
|
编译器 C++
C++之类与对象(3)(上)
C++之类与对象(3)
16 0
|
17天前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
17 1
|
27天前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)