智能指针的使用

智能指针背后的思想

  • 普通指针的弊端:delete不被执行,忘了释放内存,导致内存泄漏
  • 如果在对象过期时,让它的析构函数删除指向的内存,这正是auto_ptr , unique_ptr , shard_ptr背后的思想

使用

模板类auto_ptr

template<class x> class auto_ptr{
public:
    explicit auto_ptr(x* p = 0) throw();
    ...
}
auto_ptr<double> pd(new double);
	//pd指向double的一个智能指针,new double 替代 double *pd
auto_ptr<string> pd(new string);
	//new string 替代 string *pd
  • new double 是new返回的指针,指向新分配的内存块
  • 可以用*Pd 解除引用操作,访问结构成员(pd->name)

注意事项

问题

auto_ptr<string> ps(new string("I WIN!"));
auto_ptr<strng> vocation;
vocation = ps;
  • 两个智能指针都指向一个string对象,ps过期和vocation过期时,会试图删除同一个对象两次

方法

  • 定义赋值运算符,让其执行深复制,这样两个指针将指向不同的对象,其中的一个对象时另一个对象的副本

  • 对于对象,只能有一个智能指针拥有它。这样只有拥有对象的智能指针的构造函数才会删除该对象。

    • 然后,可以让赋值操作符转让所有权

    • auto_ptr 和 unique_ptr 就是这样的策略

    • auto_ptr

    • auto_ptr<string> p1(new string("I WIN!"));
      auto_ptr<strng> p2;
      p2 = p1;
      
      • p2接管string对象的所有权时,p1的所有权将被剥夺,虽然可以防止p1删除string对象。防止删除同一个对象两次
      • 但如果试图使用p1,这是件坏事,p1不再指向有效的数据
    • unique_ptr

    • unique_ptr<string> p3(new string("I WIN!"));
      unique_ptr<strng> p4;
      p4 = p3;
      
      • 编译不通过,第3行报错,避免了访问p3,而p3不再指向有效数据的问题。
      • 因此unique_ptr 比auto_ptr更安全
      • 编译阶段比潜在的程序崩溃更安全
    • 而以下编译通过,可以运行

      • unique_ptr<strng> p4;
        p4 = unique_ptr<string>(new string("I WIN!");
        
      • 因为是个临时右值

    • 使用new分配内存,才能使用auto_ptr 和 shared_ptr ,使用new[] 不能使用它们

      • 而不使用new分配内存时,不能使用它们,必须要用new分配,才能使用
    • unique_ptr只能使用new 和 new[]分配内存

  • 引用计数,例如:赋值时,计数将加1,而指针过期时,计数将减1,。仅当最后一个指针过期时,才调用delete,这是share_ptr的策略

    • 适用于程序要使用多个指向同一对象的的指针。
    • 当unique_ptr 为右值时,可以将其赋给shared_ptr,shared_ptr将接管原来归unique_ptr的对象

//===============================================================
//FileName:
//          smrtptrs.cpp
//Date:
//          2019/11/25
//Author:
//          khoing(https://blog.csdn.net/qq_45391763)
//===============================================================


// smrtptrs.cpp -- using three kinds of smart pointers
#include <iostream>
#include <string>
#include <memory>//使用智能指针必须包含

class Report
{
private:
	std::string str;
public:
	Report(const std::string s) : str(s) { //相当于this.s = str
		std::cout << "Object created!\n"; 
	}
	~Report() { 
		std::cout << "Object deleted!\n";
	}
	void comment() const { 
		std::cout << str << "\n";
	}
};

int main()
{
	{
		std::auto_ptr<Report> ps(new Report("using auto_ptr"));
		ps->comment();   // use -> to invoke a member function
	}
	{
		std::shared_ptr<Report> ps(new Report("using shared_ptr"));
		ps->comment();
	}
	{
		std::unique_ptr<Report> ps(new Report("using unique_ptr"));
		ps->comment();
	}
	// std::cin.get();  
	return 0;
}

// fowl.cpp  -- auto_ptr a poor choice
#include <iostream>
#include <string>
#include <memory>

int main()
{
    using namespace std;
    auto_ptr<string> films[5] =
    {
        auto_ptr<string> (new string("Fowl Balls")),
        auto_ptr<string> (new string("Duck Walks")),
        auto_ptr<string> (new string("Chicken Runs")),
        auto_ptr<string> (new string("Turkey Errors")),
        auto_ptr<string> (new string("Goose Eggs"))
    };
    auto_ptr<string> pwin;
    pwin = films[2];   // films[2] loses ownership

    cout << "The nominees for best avian baseball film are\n";
    for (int i = 0; i < 5; i++)
        cout << *films[i] << endl;
    cout << "The winner is " << *pwin << "!\n";
    // cin.get();
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值