zoukankan      html  css  js  c++  java
  • 类的拷贝控制

    类的行为:

    1. 像值
    2. 像指针
    • 类的行为像值,意味着它应该也有自己的状态。当我们拷贝一个像值的对象时,副本和原对象时完全独立的。改变副本不会对原对象有任何影响,反之亦然。
    • 行为像指针的类则共享状态。当我们拷贝一个这种类的对象时,副本和原对象使用相同的底层数据。改变副本也会改变原对象,反之亦然。

    行为像值的类

    //HasPtrAsVal.h
    class HasPtrAsVal
    {
    public:
    	HasPtrAsVal(const std::string &s = std::string()) :ps(new std::string(s)), i(0)
    	{
    	}
    	
    	//对ps 指向的string,每个HasPtrVal对象都有自己的拷贝
    	HasPtrAsVal(const HasPtrAsVal &p) :ps(new std::string(*p.ps)), i(p.i)
    	{
    
    	}
    
    	HasPtrAsVal& operator=(const HasPtrAsVal &);
    	~HasPtrAsVal()
    	{
    		delete ps;
    	}
    
    private:
    	std::string *ps;
    	int i;
    };
    
    //HasPtrAsVal.cpp
    //当编写一个赋值运算符时,一个好的模式是先将右侧运算对象拷贝到一个局部临时对象中。
    //当拷贝完成后,销毁左侧运算对象的现有成员就是安全的了。
    //一旦左侧运算对象的资源被销毁,就只剩下将数据从临时对象拷贝到左侧运算对象的成员中了。 HasPtrAsVal& HasPtrAsVal::operator=(const HasPtrAsVal &rhs) { auto newp = new string(*rhs.ps);//拷贝底层string delete ps;//释放旧内存 ps = newp;//从右侧运算对象拷贝数据到本对象 i = rhs.i; return *this; }

      

    行为像指针的类

    令一个类展现类似指针的行为的最好方法是使用shared_ptr来管理类中的资源。

    但是,有时我们希望直接管理资源。在这种情况下,引用计数就相当有用。用它来记录有多少用户共享它指向的对象,当没有用户使用对象时,释放资源。

    //HasPtrAsPtr.h
    class HasPtrAsPtr
    {
    public:
    	//构造函数分配新的string和新的计数器,将计数器置1
    	HasPtrAsPtr(const std::string& s = std::string()) :ps(new std::string(s)), i(0), use(new std::size_t(1)) 
    	{
    	};
    
    	HasPtrAsPtr(const HasPtrAsPtr &p) :ps(p.ps), i(p.i), use(p.use)
    	{
    		++*use;//拷贝时计数器+1
    	}
    
    	HasPtrAsPtr& operator=(const HasPtrAsPtr&);
    	~HasPtrAsPtr();
    
    private:
    	std::string *ps;
    	int i;
    	std::size_t *use;	//用来记录有多少个对象共享*ps的成员
    };
    
    
    //HasPtrAsPtr.cpp
    //拷贝赋值运算符执行类似拷贝构造函数和析构函数的工作
    //1、它必须递增右侧运算对象的引用计数(即,拷贝构造函数)
    //2、并递减左侧运算对象的引用计数,在必要时释放使用的内存(即,析构函数的工作) HasPtrAsPtr & HasPtrAsPtr::operator=(const HasPtrAsPtr & rhs) { // TODO: 在此处插入 return 语句 ++*rhs.use; //递增右侧运算对象的引用计数 if (--*use == 0)//递减本对象的引用计数 { delete ps;//如果没有其他用户,释放本对象分配的成员 delete use; } ps = rhs.ps;//将数据从rhs拷贝到本对象 i = rhs.i; use = rhs.use; return *this; } HasPtrAsPtr::~HasPtrAsPtr() { if (--*use == 0)//如果引用计数变为0 { delete ps;//释放string 内存 delete use;//释放计数器内存 } }

      

      

  • 相关阅读:
    python删除列表重复元素
    maven常用打包命令
    python开发之函数
    手把手教你用Strace诊断问题
    python引用列表--10
    Python中open函数怎么操作文件--9
    python数据操作--8
    图解源码之FutureTask篇(AQS应用)
    图解源码之java锁的获取和释放(AQS)篇
    图解线程池工作机制,手写线程池?
  • 原文地址:https://www.cnblogs.com/zhehan54/p/5389308.html
Copyright © 2011-2022 走看看