用智能指针实行所有权

现在我们讨论下使用返回指针的函数的潜在错误。假设有一个函数返回一个指向某个MyClass类型的对象的指针。

MyClass* MyFactoryClass::Create(const Inputs& inputs);

这个函数的一个非常显而易见的问题是,它的调用者是否负责删除这个对象?或者说这个指针所指向的MyClass类的实例是MyFactoryClass所拥有的实例?这个问题显然应该在声明这个函数的头文件中以注释的形式说明。但在软件的世界里,实际上很少能够做到这样。但是,即使函数的作者确实提供了一个注释,表示这个函数在堆上创建了一个新对象,并且由它的调用者负责删除这个对象,我们将会发现自己面临这样一种处境:每当我们接到一个由函数调用所返回的指向某个对象的指针时,我们需要记得检查注释(或者在没有注释时,检查代码本身)来推断是否由我们负责删除这个对象。正如前面所说的,我们应该更多地依赖编译器而不是程序员。因此,实行这个对象所有权的一种可靠方法是让函数返回一个智能指针。例如:

RefCountPtr<MyClass> MyFactoryClass::Create(const Inputs& inputs);

这种设计使函数所返回的对象的所有权毫无争议,不会留下内存泄露的机会。另一方面,如果觉得引用计数指针速度过慢不适合需要,也可以返回一个作用域指针。但这样就产生了一个问题:ScopedPtr<MyClass> 无法被复制,因此不能按照传统方法返回:

ScopedPtr<MyClass> MyFactoryClass::Create(const Inputs& inputs)
{
	ScopedPtr<MyClass> result(new MyClass(inputs));
	return result; //无法通过编译
}

因此,解决这个问题的方法如下:

ScopedPtr<MyClass> result;//创建一个空的作用域指针
       //填充它
void MyFactoryClass::Create(const Inputs& inputs,ScopedPtr<MyClass>& result);

我们创建一个包含NULL值的作用域指针,并让MyFactoryClass::Create()方法填充他。这个方法也不会使这个函数所创建的对象的所有权出现错误。如果不确定应该返回哪种指针,可以选择下列方案之一:

  • 如果需要,返回速度更快的ScopedPtr,并使用它的Release()方法转移所有权。
  • 同时通过两种方法

还有一种相反的情况是,SomeClass::Find()方法返回一个指向一个对象的指针,但用户并不拥有这个对象的所有权:

//返回一个指向一个结果的指针,调用者“并不拥有这个结果的所有权”
MyClass* SomeClass::Find(const Inputs& inputs);

这种情况下,这个函数所返回的指针,指向属于SomeClass内部的某个对象的一个对象。

对于上述第一个问题,SomeClass类认为自己将负责删除它刚返回的那个指针所指向的MyClass实例,因此会在未来的某个时刻将它删除。在这种情况下,如果这个函数的用户将删除他所接收到的指针,这个实例将被删除不止一次,这显然不是个好主意。其次,这个实例可能是一个vector模板中使用new[]操作符(带方括号)创建的一个MyClass对象数组的一部分,而现在我们将使用不带方括号的delete操作符从这个数组中删除一个对象。这同样不是个好的做法。最后,MyClass实例可能是在堆栈上创建的,根本不应该使用delete操作符进行删除。

在这种情况下,任何试图删除我们并不拥有的对象的行为(直接删除,或者把它赋值给一个将接收对象所有权的任何类型的智能指针)将会导致灾难。返回这种指针的一种合适的方法是返回一个”半智能“指针,它并不拥有它所指向的对象的所有权。

总结:为了避免内存泄露,建议遵从以下规则:

  • 每次使用new操作符创建一个对象时,立即把结果赋值给一个智能指针(推荐使用引用计数指针或作用域指针)
  • 使用new操作符时不要带方括号。如果创建一个数组,可以创建一个新的vector模板,它表示单个对象。
  • 避免循环引用
  • 在编写返回一个指针的函数时,应该返回一个智能指针而不是原始指针,以实行结果的所有权。

用智能指针实行所有权

时间: 2024-10-04 08:47:20

用智能指针实行所有权的相关文章

【C++深入浅出】智能指针之auto_ptr学习

起:  C++98标准加入auto_ptr,即智能指针,C++11加入shared_ptr和weak_ptr两种智能指针,先从auto_ptr的定义学习一下auto_ptr的用法. template<class _Ty> class auto_ptr { // wrap an object pointer to ensure destruction public: //定义_Myt类型,作用域局限于类中,便于书写和理解 typedef auto_ptr<_Ty> _Myt; typ

boost智能指针之shared_ptr和weak_ptr

std::auto_ptr很多的时候并不能满足我们的要求,比如auto_ptr不能用作STL容器的元素.boost的smart_ptr中提供了4种智能指针和2种智能指针数组来作为std::auto_ptr的补充. shared_ptr<boost/shared_ptr.hpp>:使用shared_ptr进行对象的生存期自动管理,使得分享资源所有权变得有效且安全. weak_ptr<boost/weak_ptr.hpp>:weak_ptr 是 shared_ptr 的观察员.它不会干

(转)剖析C++标准库智能指针(std::auto_ptr)

不可否认,资源泄露(resource leak)曾经是C++程序的一大噩梦.垃圾回收 机制(Garbage Collection)一时颇受注目.然而垃圾自动回收机制并不能 满足内存管理的即时性和可视性,往往使高傲的程序设计者感到不自在. 况且,C++实现没有引入这种机制.在探索中,C++程序员创造了锋利的 "Smart Pointer".一定程度上,解决了资源泄露问题. 也许,经常的,你会写这样的代码: //x拟为class: // class x{ // public: // int

智能指针的原理和简单实现

什么是智能指针? 智能指针实质上是一个类,定义一个类来封装资源的分配和释放.这个类的构造函数中传入一个指针,完成资源的分配和初始化.在析构函数中释放传入的该指针,完成资源的释放. 为什么要用智能指针? 智能指针就是智能,自动化的管理指针所指向的动态资源. 例如以下情况:代码中经常会忘记释放动态开辟的内存资源,导致内存泄露. // case1 void Test2() {  int* p1 = new int(2);  bool isEnd = true;  //...  if (isEnd)  

C++智能指针简单剖析

导读 最近在补看<C++ Primer Plus>第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑.C++面试过程中,很多面试官都喜欢问智能指针相关的问题,比如你知道哪些智能指针?shared_ptr的设计原理是什么?如果让你自己设计一个智能指针,你如何完成?等等--.而且在看开源的C++项目时,也能随处看到智能指针的影子.这说明智能指针不仅是面试官爱问的题材,更是非常有实用价值. 下面是我在看智能指针时所做的笔记,希望能够解决你对智能指针的一些困扰. 目录

webkit智能指针 - RefPtr, PassRefPtr

历史 2005年之前,Webkit中很多对象都采用引用计数的方式.它们通过继承RefCounted]类模板来实现这种模式.RefCounted主要是实现了ref()和deref()两个函数.在需要引用对象时要调用ref()增加引用计数,在不再需要对象时,要调用deref()函数减少引用计数.ref()和deref()需要成对出现.这和使用new/delete一样,多调用.少调用.没调用的问题总是时有发生.如果能由编译器自动完成ref, deref的调用,C/C++编程的bug至少也可以减少一半以

C++ Primer笔记8_动态内存_智能指针

1.动态内存 C++中,动态内存管理是通过一对运算符完成的:new和delete.C语言中通过malloc与free函数来实现先动态内存的分配与释放.C++中new与delete的实现其实会调用malloc与free. new分配: 分配变量空间: int *a = new int; // 不初始化 int *b = new int(10); //初始化为10 string *str = new string(10, ); 分配数组空间: int *arr = new int[10];//分配的

智能指针简介

智能指针用于解决常规指针所带来的内存泄露.重复释放.野指针等内存问题.智能指针基于这样的事实得以发挥作用:定义在栈中的智能指针,当超出其作用域时,会自动调用它的析构函数,从而可以释放其关联的内存资源. 之前C++标准库中定义的智能指针std::auto_ptr<T>,因其设计存在缺陷,所以已不再推荐使用.C++11引入了新的智能指针:unique_ptr.shared_ptr和weak_ptr. 一:unique_ptr unique_ptr类似于auto_ptr.两个unique_ptr实例

C++智能指针剖析(下)boost::shared_ptr&amp;其他

1. boost::shared_ptr 前面我已经讲解了两个比较简单的智能指针,它们都有各自的优缺点.由于 boost::scoped_ptr 独享所有权,当我们真真需要复制智能指针时,需求便满足不了了,如此我们再引入一个智能指针,专门用于处理复制,参数传递的情况,这便是如下的boost::shared_ptr. boost::shared_ptr 属于 boost 库,定义在 namespace boost 中,包含头文件#include<boost/smart_ptr.hpp> 便可以使