ToB企服应用市场:ToB评测及商务社交产业平台

标题: 《Effective C++》第三版-3. 资源管理(Resource Management) [打印本页]

作者: 缠丝猫    时间: 2024-5-18 21:31
标题: 《Effective C++》第三版-3. 资源管理(Resource Management)
目录

前几章的条记多有不敷,这一章会持续改进
条款13:以对象管理资源(Use objects to manage resources)

关键想法

考虑以下易出错的例子:
  1. class Investment { ... };  //投资类型继承体系中的root类
  2. //工厂函数,指向Investment继承体系内的动态分配对象,参数省略
  3. Investment* createInvestment {};
  4. void f()
  5. {
  6.         Investment* pInv = createInvestment();  //调用工厂函数
  7.         ...  //若这里return则无法执行delete
  8.         delete pInv;  //释放pInv所指对象
  9. }
复制代码
办理方案:把资源放进对象,可利用析构函数自动调用机制确保资源释放
以对象管理资源的两个关键想法:
智能指针

auto_ptr
auto_ptr在C++11中已被弃用,以下简要介绍
  1. void f()
  2. {
  3.         std::auto_ptr<Investment> pInv(createInvestment());
  4.         ...
  5. }  //auto_ptr的析构函数自动删除pInv
  6. std::auto_ptr<Investment< pInv1(createInvestment());
  7. std::auto_ptr<Investment< pInv2(pInv1);  //现在pInv2指向对象,pInv1为null
  8. pInv1 = pInv2;  //现在pInv1指向对象,pInv2为null
复制代码
优缺点

偶然必须取得RAII对象内的原始资源,考虑用于字体的RAII类:
  1. void f()
  2. {
  3.         std::tr1::shared_ptr<Investment> pInv(createInvestment());
  4.         ...
  5. }  //shared_ptr的析构函数自动删除pInv
  6. void f()
  7. {
  8.         ...
  9.         std::tr1::shared_ptr<Investment> pInv1(createInvestment());
  10.         std::tr1::shared_ptr<Investment> pInv2(pInv1);  //指向同一个对象
  11.         pInv1 = pInv2;  //同上
  12.         ...
  13. }  //pInv1和pInv2被销毁,他们所指的对象也被销毁
复制代码
  1. std::auto_ptr<std::string> aps(new std::string[10]);  //会调用错误形式的delete
  2. std::tr1::shared_ptr<int> spi(new int[1024]);  //同上
复制代码
  1. void lock(Mutex* pm);  //锁定pm所指的互斥器
  2. void unlock(Mutex* pm);  //解除互斥器的锁定
  3. //管理机锁的类,符合RAII守则
  4. class Lock {
  5. public:
  6.         explicit Lock(Mutex* pm)
  7.                 : mutexPrt(pm)
  8.         { lock(mutexPtr); }
  9.         ~Lock() { unlock(mutexPtr); }
  10. private:
  11.         Mutex *mutexPtr;
  12. };
  13. //客户对Lock的用法符合RAII方式
  14. Mutex m;
  15. ...
  16. {
  17.         Lock ml(&m);
  18.         ...
  19. }
复制代码
Tips:
条款16:成对使用new和delete时要采取相同形式(Use the same form in corresponding uses of new and delete)
  1. Lock m11(&m);  //锁定m
  2. Lock m12(m11);  //将m11复制到m12上
复制代码
以上程序的举动不明确:
  1. class Lock {
  2. public:
  3.         explicit Lock(Mutex* pm)  //以Mutex初始化shared_ptr
  4.                 : mutexPtr(pm, unlock)  //以unlock函数作为删除器
  5.         {
  6.                 lock(mutexPtr.get());
  7.         }
  8. private:
  9.         std::tr1::shared_ptr<Mutex> mutexPtr;  //使用shared_ptr替换raw pointer
  10. };
复制代码
使用typedef需要考虑相同的问题(下例中数组使用typedef并不合适,容易产生错误,仅做说明):
  1. class Investment {
  2. public:
  3.         bool isTaxFree() const;
  4.         ...
  5. }
  6. Investment* createInvestment();  //工厂函数
  7. std::tr1::shared_ptr<Investment> pInv(createInvestment());
  8. int daysHeld(const Investment* pi);  //返回投资天数
  9. int days = daysHeld(pInv);  //错误!daysHeld需要Investment*而非tr1::shared_ptr
  10. //显示转换
  11. int days = daysHeld(pInv.get());
  12. //隐式转换,tr1::share_ptr重载了指针取值(pointer dereferencing)操作符(->和*)
  13. bool taxable1 = !(pInv->isTaxFree());
  14. bool taxable2 = !((*pInv).isTaxFree());
复制代码
Tips:
条款17:以独立语句奖newed对象置入智能指针(Store newed objects in smart pointers in standalone statements)

考虑涉及优先权的例子:
  1. FontHandle getFont();  //这是C API,省略参数
  2. void releaseFont(FontHandle fh);  //来自同一组
  3. class Font {  //RAII类
  4. public:
  5.         explicit Font(FontHandle fh)  //获得资源
  6.                 : f(fh)  //使用pass-by-value,因为C API这样做
  7.         { }
  8.         ~Font() { releaseFont(f); }  //释放资源
  9. private:
  10.         FontHandle f;  //原始字体资源
  11. };
复制代码
编译器产出processWidget调用码之前,必须首先核酸即将被传递的各个实参,其要办事情有三件:
现实执行的序次弹性很大,只能确定执行new Widget肯定先于调用tr1::shared_ptr构造函数,但调用priority的序次不愿定。若编译器选择以下序次:
则如果调用priority出现异常,那new Widget返回的指针将遗失,其将来得及放入tr1::shared_ptr内,进而导致资源走漏。即创建资源和资源转换为资源管理对象直接有可能发生异常干扰
办理方法:使用分离语句,因为编译器对于跨越语句的各项操纵没有重新排列的自由
  1. class Font {
  2. public:
  3.         ...
  4.         FontHandle get() const { return f; }  //显式转换函数
  5.         ...
  6. };
  7. void changeFontSIze(FontHandle f, int newSize);
  8. Font f(getFont());
  9. int newFontSize;
  10. ...
  11. changeFontSize(f.get(), newFontSize);
复制代码
Tips:

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4