首页 > 编程语言 >Effective C++:3.资源管理

Effective C++:3.资源管理

时间:2024-05-19 16:57:35浏览次数:17  
标签:Effective RAII C++ 资源管理 new shared ptr delete

所谓资源,就是一旦用了,就要还给系统。C++中最常见的就是动态分配内存。其他资源还包括文件描述符、互斥锁等等

1.条款13:以对象管理资源

把资源放到对象内,那么就可以通过C++的析构函数自动调用的机制去确保资源被释放。这种观念常被称为RAII(资源取得时机就是初始化时机)
智能指针shared_ptr就是这种思想的实现:

std::shared_ptr<Cat> cat;

以上的代码声明了一个Cat类型的共享指针,shared_ptr会确保Cat的销毁
总结: 把资源放到对象内,那么就可以通过C++的析构函数自动调用的机制去确保资源被释放。,而shared_ptr则是这种想法的一个优雅的实现

2.条款14:在资源管理类中小心copying行为

RAII对象必须一并复制它所管理的类,所以资源的copying行为决定RAII对象的copying行为。RAII对象的复制我们一般有两种需求:

  • 禁止复制,可以参照条款6实现,或者参照 C++11,声明delete显式删除拷贝构造函数
  • 希望底层资源能够在最后一个使用者不使用后才删除:施行指针计数法,把资源声明为shared_ptr
    总结:
  • 复制RAII对象必须复制它的所有资源,所以资源的copying行为决定RAII对象的copying行为
  • 普遍而常见的RAII拷贝行为是抑制拷贝、施行指针计数法

3.条款15:在资源管理类中提供对原始资源的访问

API往往要求访问原始资源,所以每一个RAII类应该提供一个取得原始资源的,主要有了两种方式:

  • 显式转换
    1. 在shared_ptr内可以利用get函数显式获取资源

std::shared_ptr<Cat> cat;
cat.get()                //显式获取资源
  2. 在自己实现类中则是
FontHandle getFont()     //这是C语言的API函数
class Font{
public:
  FontHandle get() const{return f;}
private:
  FontHandle f;
}
  • 隐式转换:
FontHandle getFont()     //这是C语言的API函数
class Font{
public:
  operator FontHandle() const{return f;}
private:
  FontHandle f;
}

显式转换比较安全,隐式转换比较方便。
总结:

  • API往往要求访问原始资源,所以每一个RAII类应该提供一个取得原始资源的,主要有了两种方法,显式转换和隐式转换,显式转换比较安全,隐式转换方便用户。

4.条款16:成对使用new和delete时要采取相同形式

C++ new和delete 有两种形式

  1. new或者delete一个对象
string * hello= new string("hello");
delete hello;
  1. new或者delete一个对象组成的数组
string * hellos = new string[100]
delete hellos [];

如果对上述两种形式混用,会出现错误,因需要匹配使用。
总结: C++ new和delte 有两种形式:new或者delete一个对象,new或者delete一个对象组成的数组。需要搭配使用

5.以独立语句将newed对象置入智能指针

在使用只能指针的时候需要使用独立的语句子将newed对象置入智能指针。比如有如下的函数

int eat();
void dailyLife(shared_ptr<Cat> cat , int eaten);

用户可能会这样调用函数:

dailyLife(shared_ptr<Cat>(new Cat), eat());

C++此时需要执行:

  1. Cat构造
  2. shared_ptr构造
  3. eat函数调用
    而在C++下,这三个函数的先后顺序不一定,如果顺序是下面这样:
  4. Cat构造
  5. eat函数调用
  6. shared_ptr构造
    则会发生问题:如果eat调用函数发生异常,那么Cat构造返回的指针将会丢,因为此时Cat指针尚未被shared_ptr管理起来
    因此正确的在做法是以独立语句将newed对象置入智能指针:
shared_ptr<Cat> cat (new Cat); 
dailyLife(cat, eat());

总结: 以独立语句将newed对象置入智能指针

标签:Effective,RAII,C++,资源管理,new,shared,ptr,delete
From: https://www.cnblogs.com/shell-zlj/p/18197045

相关文章

  • 【每周例题】力扣 C++ 一年中的第几天
    一年中的第几天题目一年中的第几天 思路分析1.substr函数分割字符串,stoi函数将字符串转为十进制stoi函数介绍substr函数介绍2.判断是否为闰年,如果是闰年,则二月的天数+1代码#include<bits/stdc++.h>usingnamespacestd;intmain(){ intmonths[13]={0,31,28,3......
  • UE4 C++ 攀爬功能
    UE中的TEXT()UE中使用TEXT()包含字符串后,将字符串转换为宽字符,其将被处理为支持Unicode和跨平台兼容性,而普通类型的字符串为一个窄字符类型,可能在跨平台出现问题。最主要的问题是在FString的构造函数中是接受TCHAR的所以对于FStringFNameFTEXT的构造需要传入TEXT("xxxx")。......
  • 百度 Apollo 使用 bazel 编译 C++ Boost 依赖出现 undefined reference to `boost::pyth
    CSDN搬家失败,手动导出markdown后再导入博客园因为一些原因,楼主想在Apollo自动驾驶框架里使用Boost.python工具来用C++调用Python,从网上找了个例子想编译下试试。C++代码如下(boost.python/EmbeddingPython-PythonWiki):#include<boost/python.hpp>usingnamesp......
  • C/C++技巧
    1.三目运算符语法:表达式1?表达式2:表达式3。表达式1为真则执行表达式2,否则执行表达式3。相比if语句,三目运算符短小简洁,适当使用可以提高代码可读性。另外,如果三目运算符返回左值,可以继续赋值。举例#include<iostream>usingnamespacestd;intmain(){system("......
  • C++学习----make
    基本规则:touchmain.cadd.csub.cadd.hsub.h#新建以上文件main函数:intmain(void){return0;}Makefile文件:main:main.oadd.osub.ogcc-Wall-gmain.oadd.osub.o-omainmain.o:main.cgcc-Wall-g-cmain.c-omain.oadd.o:add.cadd.h......
  • C++学习----gcc
    gcc编译步骤 静态库使用步骤hello_fn.h#ifndef_HELLO_FN_H#define_HELLO_FN_Hvoidhello(constchar*name);#endifhello_fn.c#include<stdio.h>#include"hello_fn.h"voidhello(constchar*name){printf("hello%S!!!\n",name);......
  • Qt/C++音视频开发74-合并标签图形/生成yolo运算结果图形/文字和图形合并成一个/水印滤
    一、前言在使用yolo做人工智能运算后,运算结果除了一个方框,还可能需要增加文字显示在对应方框上,以便标记是何种物体,比如显示是人还是动物,或者还有可能追踪人员,显示该人员的姓名。这种应用场景非常普遍,而且非常有必要,可以非常直观的直接看到对应移动的物体是什么。当然也有个缺点,就......
  • algo c++ 常用接口
    接口网站cppreferencesetunorder_set//unorder_setunorder_set<T>u_set;//insertu_set.insert(Tt);//findandjudgeiteratorit=u_set.find(Tt);if(u_set.find(t)!=it.end()){}//删除u_set.erase(t);技巧如果想要通过一种数据类型种的值构建另一种......
  • C++读取配置文件
    1、读取=号的配置文件(或者:)的配置。#include<iostream>#include<fstream>#include<sstream>#include<map>#include<string>std::map<std::string,std::string>read_config(conststd::string&filename){std::map<std::st......
  • C++ 初始化列表(Initialization List)
    请注意以下继承体系中各class的constructors写法:1classCPoint2{3public:4CPoint(floatx=0.0)5:_x(x){}67floatx(){return_x;}8voidx(floatxval){_x=xval;}9protected:10float_x;11};1213classCPoint2d:......