技术分享会之——智能指针

由于之前也只是了解智能指针,要我说估计只能说个它是干什么的,用不了几分钟。

昨天花了一天时间各种百度,算是对智能指针有了一点了解,这篇文章基本就是这次分享会的PPT的copy,没有底层的东西,多是概念。

我觉得理解智能指针需要了解它发展的三个过程:起因,经过,结果。这篇文章主要讲述的是起因,经过和结果等以后工作了,实际接触了再说吧。

起因:

1.为什么需要智能指针

我们先看两个例子

一:内存泄露

<pre name="code" class="cpp">//内存泄露
#include <stdio.h>
#include <iostream>
using namespace std;
class A
{
public:
    A(char *cstr);
    A(const A &ca);
    A();
    ~A();
    A operator=(const A &ca);
private:
    char *str;
};
A::A(char *cstr)
{
    str = new char[20];
    strcpy(str, cstr);
}
A::A(const A &ca)
{
    str = new char[20];
    strcpy(str, ca.str);
}
A A::operator=(const A &ca)
{
    str = new char[20];
    strcpy(str, ca.str);
    return str;
}
A::A() : str(new char[20])
{
    strcpy(str, "Welcome!");
}
A::~A()
{
    delete[] str;
    str = NULL;
}
int main(void)
{
    A a("Hello world!");
    A b(a);
    A c;
    c = b;

    return 0;
}

A A::operator=(constA &ca)

{

str =new char[20];

strcpy(str, ca.str);

return str;

}

?罪魁祸首就是这段函数,当c=b的时候,就已经发生了内存泄露的隐患。

?原因:

–Ac 这句话调用了构造函数,已经在内存空间new了一块空间。

–c=b 这句调用了操作符重载函数,同样new了一块空间,这样上一次new的空间我们就找不到了。

–即使在析构的时候delet了第二次申请的空间,但是依然无法避免内存泄露的问题。

解决办法:

一:

A::operator=(constA &ca)

{

strcpy(str, ca.str);

}

但是前提是我们已经申请了空间。

二:

A::operator=(const A &ca)

{

delete[] str;

str = new char[20];

strcpy(str, ca.str);

}

这是个比较危险的方法,如果str没有被初始化或者已经被delet过了,程序就会发生致命错误!

三:

A::operator=(const A &ca)

{

if(str == NULL)

{

str = new char[20];

}

strcpy(str, ca.str);

}

这是最好的方法,可以在很多源码中发现都是用了这种方法。但是需要注意的是str在没有被分配前必须初始化为NULL,因为在未分配和初始化NULL的时候,str不一定是个空指针,还可能是一个野指针。

二:悬垂指针

#include <stdio.h>
#include <iostream>
#include <windows.h>
using namespace std;

int *p=NULL;
void fun()
{
	int i=10;
	p=&i;
}

int main()
{
	fun();
	cout<<"*p= "<<*p<<endl;//输出p=10
	Sleep(1000);
	cout<<"*p= "<<*p<<endl;//输出p=0
	return 0;
}

两次输出的值不一样,因为程序发生了悬垂指针的错误。具体和操作系统的堆栈管理方式有关,感兴趣可以去百度~

在调用fun()函数的时候,指针P指向了这个模块内的一个整型,当这个模块刚刚返回,这个整型还是存在的,但是过了一会(具体多久还要看具体情况),它被系统释放掉了,那么P所指向的内容就不是我们能控制的了,这就是悬垂指针。

悬垂指针的定义:指向曾经存在的对象,但该对象已经不再存在了,此类指针称为悬垂指针。结果未定义,往往导致程序错误,而且难以检测。

以上可以说是智能指针的起因了吧,我做过一些小项目,所以能深深体会到智能指针的必要性。有时候编写程序的时候总会new一些东西,要么忘了销毁,要么搞不清楚在哪里销毁,这也许和我经验不足有关,但是难保一些大神们不会犯这种错。

2.为什么不自建“智能”指针

这里的为什么的主语-“我”特指像我这样的新手。既然new和delete要成对的出现,那我们为什么不自己封装一个类,创建的时候new,析构的时候delete呢?之所以特指,是因为新手考虑问题都比较片面,这样除了同样会造成上面的内存泄露的问题,还会造成其他错误。

class intptr
{
private:
 int* m_p;
public:
 intptr(int* p){ m_p = p; }
 ~intptr(){ delete m_p; }
 int& operator*(){ return *m_p; }
};

这就是上面想法的一个例子,当我们这样调用的时候不会出现问题:

somefunction()
{
 intptr pi(new int);
 *pi = 10;
 int a = *pi;
}

但是如果换种方式:

void somefunction()
{
 intptr pt1(new int);
 intptr pt2(new int);
 *pt1 = 10;
 pt2 = pt1;
}

问题就出现了,pt2指向了pt1所指向的内容,那么pt2原来所指向的内容我们就无法获取和销毁了,这也是一种内存泄露。另外在程序块结束后,这块内存将要被销毁两次,这明显是不符合逻辑的。

经过:

1.引用计数

由于以上问题,我们又引入了引用计数这个概念。

在引用计数中,每一个对象负责维护对象所有引用的计数值。当一个新的引用指向对象时,引用计数器就递增,当去掉一个引用时,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。

2.几种智能指针的概述

这里只是概述,不说用法和分析源码

智能指针有很多:

std::auto_ptr、

boost::scoped_ptr、

boost::shared_ptr、

boost::scoped_array、

boost::shared_array、

boost::weak_ptr、

boost::intrusive_ptr

auto_ptr

缺点OR特性:

不能作为STL的成员(C++标准明确禁止这样做,否则可能会碰到不可预见的结果)

不能共享所有权(不一定是缺点,有它一定的应用)

不能指向数组

不能通过赋值操作来初始化

std::auto_ptr<int> p(new int(42)); //OK

std::auto_ptr<int> p = new int(42); //ERROR

scoped_ptr

?boost::scoped_ptr的实现和std::auto_ptr非常类似,都是利用了一个栈上的对象去管理一个堆上的对象,从而使得堆上的对象随着栈上的对象销毁时自动删除。不同的是,boost::scoped_ptr有着更严格的使用限制——不能拷贝。这就意味着:boost::scoped_ptr指针是不能转换其所有权的。

?缺点OR特性:

–不能转换所有权

boost::scoped_ptr所管理的对象生命周期仅仅局限于一个区间(该指针所在的"{}"之间),无法传到区间之外,这就意味着boost::scoped_ptr对象是不能作为函数的返回值的(std::auto_ptr可以)。

–不能共享所有权

这点和std::auto_ptr类似。这个特点一方面使得该指针简单易用。另一方面也造成了功能的薄弱——不能用于stl的容器中。

–不能用于管理数组对象

由于boost::scoped_ptr是通过delete来删除所管理对象的,而数组对象必须通过deletep[]来删除,因此boost::scoped_ptr是不能管理数组对象的,如果要管理数组对象需要使用boost::scoped_array类

shared_ptr

?缺点OR特性:

–1. shared_ptr是Boost库所提供的一个智能指针的实现,shared_ptr就是为了解决auto_ptr在对象所有权上的局限性(auto_ptr是独占的),在使用引用计数的机制上提供了可以共享所有权的智能指针.

–2. shared_ptr比auto_ptr更安全

–3. shared_ptr是可以拷贝和赋值的,拷贝行为也是等价的,并且可以被比较,这意味这它可被放入标准库的一般容器(vector,list)和关联容器中(map)。

weak_ptr

一种弱引用

3.强引用与弱引用

一个强引用当被引用的对象活着的话,这个引用也存在(就是说,当至少有一个强引用,那么这个对象就不能被释放)。boost::share_ptr就是强引用。

相对而言,弱引用当引用的对象活着的时候不一定存在。仅仅是当它存在的时候的一个引用。弱引用并不修改该对象的引用计数,这意味这弱引用它并不对对象的内存进行管理,在功能上类似于普通指针,然而一个比较大的区别是,弱引用能检测到所管理的对象是否已经被释放,从而避免访问非法内存

当时举的鸭子和鸡的例子这里就不说了

结果:

现在的结果就是我们上面看到那些已经封装好的智能指针,至于为什么没有放到结果这里,是因为我想它还会继续发展,会越来越简单方便。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-08 06:28:00

技术分享会之——智能指针的相关文章

enote笔记法使用范例(2)——指针(1)智能指针

要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在<C++ Primer>这样解释的,“通过定义一个类来封装资源的分配和释放,可以保证正确释放资源” 核心:C++98提供了语言机制:对象([!值语意对象])在超出作用域,,析构函数会被自动调用 [如果构造函数中抛出异常,则不会调用析构函数.只有构造函数正确地执行,构建对象成功,才会调用析构函数] &l

C++技术问题总结-第9篇 智能指针

智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,能够在适当的时间自动删除指向的对象外,能够确保正确的销毁动态分配的对象. 标准库的智能指针为auto_ptr.boost库的智能指针族在功能上做了扩展. 1.auto_ptr auto_ptr注意事项如下. ①auto_ptr不能共享所有权. ②auto_ptr不能指向数组. ③auto_ptr不能作为容器成员. ④不能通过赋值操纵来初始化auto_ptr. 2.boost_ptr boost库对智能指针族做了扩展,使用

基于C/S架构的3D对战网络游戏C++框架 _05搭建系统开发环境与Boost智能指针、内存池初步了解

本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): 1.实现基本通信框架,包括对游戏的需求分析.设计及开发环境和通信框架的搭建: 2.实现网络底层操作,包括创建线程池.序列化网络包等: 3.实战演练,实现类似于CS反恐精英的3D对战网络游戏: 技术要点:C++面向对象思想.网络编程.Qt界面开发.Qt控件知识.Boost智能指针.STL算法.STL.

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++智能指针的创建

zero 坐在餐桌前,机械的重复“夹菜 -> 咀嚼 -> 吞咽”的动作序列,脸上用无形的大字写着:我心不在焉.在他的对面坐着 Solmyr ,慢条斯理的吃着他那份午餐,维持着他一贯很有修养的形象 ——— 或者按照 zero 这些熟悉他本质的人的说法:假象. “怎么了 zero ?胃口不好么?”,基本填饱肚子之后,Solmyr 觉得似乎应该关心一下他的学徒了. “呃,没什么,只是 …… Solmyr ,C++ 为什么不支持垃圾收集呢?(注:垃圾收集是一种机制,保证动态分配了的内存块会自动释放,J

实战c++中的智能指针unique_ptr系列-- 使用std::unique_ptr代替new operator(错误:‘unique_ptr’ is not a member of ‘std’)

写了很多篇关于vector的博客,其实vector很便捷,也很简单.但是很多易错的问题都是vector中的元素为智能指针所引起的.所以决定开始写一写关于智能指针的故事,尤其是unique_ptr指针的故事. 这是个开始,就让我们使用std::unique_ptr代替new operator吧! 还是用程序说话: #include<iostream> int main() { while (true) int *x = new int; } 看下任务管理器中的内存: 此时使用智能指针unique

智能指针 与 oc中的指针

智能指针 与 oc中的指针 智能指针的原理及实现 当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝:另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享. 智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针. 每次创建类的新对象时,初始化指针并将引用计数置为1:当对象作为另一对象的副

More Effective C++ 条款28 Smart Pointers(智能指针)

1. 智能指针(如标准库的auto_ptr,shared_ptr,weak_ptr,boost的scoped_ptr等)主要用于动态内存的管理,同时提供给用户与内置指针一样的使用方法,本条款主要涉及智能指针在构造与析构,复制和赋值,解引等方面的注意点,而非智能指针的实现细节. 2. 智能指针的构造,赋值,析构 智能指针的copy constructor,assignment operator,destructor对应于不同的观念而有不同的实现,主要有三种选择: 1).不允许对象的共享,在调用co

C++中智能指针的设计和使用

转载请标明出处,原文地址:http://blog.csdn.net/hackbuteer1/article/details/7561235      智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露.它的一种通用实现技术是 使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针.每次创建类的新对象时,初始化指针并将引用计数置为