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对象存储于智能指针内。如果不这样做,一旦异常被抛出,有可能导致难以察觉的内存泄漏。

相关文章
|
15天前
|
C++
C++(十九)new/delete 重载
本文介绍了C++中`operator new/delete`重载的使用方法,并通过示例代码展示了如何自定义内存分配与释放的行为。重载`new`和`delete`可以实现内存的精细控制,而`new[]`和`delete[]`则用于处理数组的内存管理。不当使用可能导致内存泄漏或错误释放。
|
15天前
|
C++
C++(十一)对象数组
本文介绍了C++中对象数组的使用方法及其注意事项。通过示例展示了如何定义和初始化对象数组,并解释了栈对象数组与堆对象数组在初始化时的区别。重点强调了构造器设计时应考虑无参构造器的重要性,以及在需要进一步初始化的情况下采用二段式初始化策略的应用场景。
|
15天前
|
存储 编译器 C++
C ++初阶:类和对象(中)
C ++初阶:类和对象(中)
|
15天前
|
C++
C++(十八)Smart Pointer 智能指针简介
智能指针是C++中用于管理动态分配内存的一种机制,通过自动释放不再使用的内存来防止内存泄漏。`auto_ptr`是早期的一种实现,但已被`shared_ptr`和`weak_ptr`取代。这些智能指针基于RAII(Resource Acquisition Is Initialization)原则,即资源获取即初始化。RAII确保对象在其生命周期结束时自动释放资源。通过重载`*`和`-&gt;`运算符,可以方便地访问和操作智能指针所指向的对象。
|
15天前
|
C++
C++(九)this指针
`this`指针是系统在创建对象时默认生成的,用于指向当前对象,便于使用。其特性包括:指向当前对象,适用于所有成员函数但不适用于初始化列表;作为隐含参数传递,不影响对象大小;类型为`ClassName* const`,指向不可变。`this`的作用在于避免参数与成员变量重名,并支持多重串联调用。例如,在`Stu`类中,通过`this-&gt;name`和`this-&gt;age`明确区分局部变量与成员变量,同时支持链式调用如`s.growUp().growUp()`。
|
28天前
|
存储 安全 C++
C++:指针引用普通变量适用场景
指针和引用都是C++提供的强大工具,它们在不同的场景下发挥着不可或缺的作用。了解两者的特点及适用场景,可以帮助开发者编写出更加高效、可读性更强的代码。在实际开发中,合理选择使用指针或引用是提高编程技巧的关键。
23 1
|
1月前
|
安全 NoSQL Redis
C++新特性-智能指针
C++新特性-智能指针
|
1月前
|
编译器 C++
virtual类的使用方法问题之在C++中获取对象的vptr(虚拟表指针)如何解决
virtual类的使用方法问题之在C++中获取对象的vptr(虚拟表指针)如何解决
|
30天前
|
存储 程序员 编译器
c++学习笔记08 内存分区、new和delete的用法
C++内存管理的学习笔记08,介绍了内存分区的概念,包括代码区、全局区、堆区和栈区,以及如何在堆区使用`new`和`delete`进行内存分配和释放。
37 0
|
30天前
|
存储 C++
c++学习笔记06 指针
C++指针的详细学习笔记06,涵盖了指针的定义、使用、内存占用、空指针和野指针的概念,以及指针与数组、函数的关系和使用技巧。
29 0