C++ Smart pointer

什么是smart pointer

一般在C/C++中,如果我们使用了pointer来指向某块heap区域,当不再需要这块区域的时候,我们需要手动删除它。如果忘了的话,就会产生memory leak。比如:

int* a = new int[5]; 
// no memory leak
delete[] a;

int* b = new int[5];
// memory leak

手动删除太麻烦,又容易出错,那么能不能有一种pointer,当我们不需要它之后,它能帮我们自动删除指向的内存区域呢?先不提C++所提供的smart pointer,假设我们自己想设计这样一个pointer,可以这样做:

class smartPtr{
   
public:
	obj* ptr;   // ptr是指向任何类型的obj的指针
	smartPtr(obj* p): ptr(p){
   }
	~smartPtr(){
    
		delete ptr; 
	}
};

有了这样smartPtr,我们可以这样使用它:

int main(){
   
	{
   
		// constructor smartPtr()被调用
		// p被初始化为指向obj的一个pointer
		smartPtr p = new obj();
	}
	//当p退出{}这个scope, p的destructor ~smartPtr()会被调用
	//而在~smartPtr()中,p指向的obj被自动delete了
}

可以看见,我们不需要手动调用delete来进行删除了,因为smartPtr替我们做好了这一切。而这就是C++ smart pointer的基本思想(当然,C++提供的smart pointer要fancy得多)。
Smart pointer像是一个owner。当它退出当前scope之后,它的destructor会被调用,而它的destructor会自动删除它所指向的Object。

为什么要使用smart pointer

其实在介绍什么是smart pointer的时候,就已经说明为什么要使用smart pointer了。不过这个部分我们再进行进一步地阐述。
假设我们有一个base class GeoObj,以及两个继承了GeoObj的subclasses Circle和Line:

class Coord{
   
private:
	int x, y;
public:
	Coord(int _x, int _y):x(_x), y(_y){
   }
};

class GeoObj{
   
public:
	virtual void move(Coord) = 0;
	virtual void draw() const = 0;
	virtual ~GeoObj() = default;
};

class Line : public GeoObj{
   
private:
    Coord from;
    Coord to;
public:
    Line(Coord f, Coord t): from(f), to(t){
   
        std::cout << "Line object is created!" << std::endl;
    }

    void move(Coord) override {
   }
    void draw() const override {
   }

    ~Line() override{
   
        std::cout << "Line object is deleted!" << std::endl;
    }
};

class Circle: public GeoObj{
   
private:
    Coord center;
    int rad;
public:
    Circle(Coord c, int r): center(c), rad(r){
   
        std::cout << "Circle object is created!" << std::endl;
    }

    void move(Coord) override {
   }
    void draw() const override {
   }

    ~Circle() override {
   
        std::cout << "Circle object is deleted!" << std::endl;
    }
};

然后我们创建一个存储GeoObj指针的数组 fig,并且向里面加入一个Line object和一个Circle Object。

std::vector<GeoObj*> fig;
Line* l = new Line(Coord(1,2), Coord(3,4));
Circle* c = new Circle(Coord(5,6), 7);
fig.push_back(l);
fig.push_back(c);

接下来,如果我们想要删除fig中的元素,有的人可能会想到直接使用fig.clear()。但是fig.clear()只会删除lp, cp这两个指针,却不会删除这两个指针指向的元素Line和Circle,所以如果大家试一下的话,可以在terminal看到Line和Circle的constructor被调用,destructor却没有没调用。也就是说,我们删除了指向这两个objects的指针,却没有回收这两个指针指向的内存区域。这样导致的问题就是在Garbage Collector眼中,这两块内存区域已经被某个程序使用了,但其实

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值