当前位置: 首页 > ds >正文

IO流与单例模式

单例模式

单例模式是指一个类只能有一个对象。

饿汉模式

在单例模式下,在程序开始(main函数运行前)的时候创建一个对象,这之后就不能再创建这个对象。

class HungryMan
{
public:static HungryMan* getinstance(){return &inst;}
private:HungryMan(){}HungryMan(const HungryMan& it) = delete;const HungryMan& operator=(const HungryMan& it) = delete;static HungryMan inst;//这里是声明,并不是定义,所以可以在类里面包含//实际上是全局变量与类封装融合的结果
};HungryMan HungryMan::inst;//在类外定义

饿汉模式的实现方式较为简单,但存在线程安全(如果没加锁,可能会出现new了几个单例对象出来),可能导致进程启动慢(main函数启动之前需要创建对象),无法控制单例的初始化顺序(如果不同的单例模式在不同的文件,就无法确认初始化顺序,包括单例之间有可能存在依赖,也可能存在问题)的问题。

懒汉模式

在第一次使用的时候创建。

class LazyMan
{
public:static LazyMan* getinstance(){if (inst == nullptr){inst = new LazyMan();//new出来的数据是需要释放的,但懒汉对象大部分不需要手动释放//但这个对象并不是在程序层面上释放的,而是在系统回收资源的时候释放的//那如果我们需要保存一些数据的话,要保证main函数之后要自动调用懒汉类的析构函数}return inst;}static void delinstance(){if (inst == nullptr){delete inst;inst=nullptr;}}private:LazyMan(){}LazyMan(const LazyMan& it) = delete;const LazyMan& operator=(const LazyMan& it) = delete;static LazyMan* inst;class gc{~gc(){delinstance();}};static gc delgc;
};LazyMan* LazyMan::inst = nullptr;LazyMan::gc LazyMan::delgc;

IO流

c++的IO流

C++系统实现了一个庞大的类库,其中ios为基类,其他类都是直接或间接派生自ios类,c++这个IO流实际上是和C语言保持一致的,比如说istream对标的就是scanf和printf,fstream对标的是fscanf和fprintf,sstream对标的是sscanf和sprintf。
在这里插入图片描述
在类型转换中,对于内置类型,相近的类型可以互相转换,其他的可以由构造函数来支持转换,就像自定义类型可以转化为自定义类型,内置类型也可以转换为自定义类型,自定义类型也可以转化为自定义类型。

class tmp
{
public:operator int(){if(/*输入为ctrl+z*/){return 0;}else{return /*非0*/}}
};int main()
{tmp t;int i = t;return 0;
}

标准读写

所以cin可以直接使用while(cin>>tmp),当输入其他字符,返回值就为真,如果输入ctrl+z,返回值就是假,循环就退出了。
c++默认是兼容C语言的,当c++的cin和C语言的scanf混用的时候,并不会因为缓冲区的问题而导致读取混乱,如果想关掉这种兼容,可以调用下图的函数。

cin.sync_with_stdio(false);
cout.sync_with_stdio(false);

在这里插入图片描述

文件读写

在C语言中,fgetc和fputc是用来读单个字符的,fread和fwrite是用来读写文件的,fprintf和fscanf是用来格式化读写的,但这些只能用来对内置类型做操作,在c++里,ifstream是从文件里读,ofstream是写到文件里,可以应付内置类型和自定义类型的输入和输出。
二进制读写:如果要把内存中的数据存到磁盘里,内存中的数据是由类型的,而磁盘没有,我们可以使用二进制读写,也可以使用文本读写。比如说我们要把一个结构体按二进制的形式写到磁盘里:
在这里插入图片描述

class A
{
private:int a;char b;string c;
};class Bin
{
public:Bin(const char* filename="./info.bin"):_filename(filename){}void Write(){ofstream ofs(_filename, ios_base::out | ios_base::binary);A data;ofs.write((const char*)&data, sizeof(data));}void Read(A & rA){ifstream ifs(_filename, ios_base::in | ios_base::binary);ifs.read((char*)&rA, sizeof(rA));}private:string _filename;
};

在这里插入图片描述
我们可以用read再次读取,但这样是把数据原封不动的读回来,包括地址,但这样在同一个进程就会发生浅拷贝问题,析构两次,而如果是不同的进程读取,就会出现野指针问题,因为到后来的进程读取的时候,前面进程的空间早就销毁了,根据文件拷贝回来的地址就是一个野指针,所以只要是容器都要注意不能用二进制进行读取,因为容器底层都相对复杂。
文本读写:如果要正常读写到文件里和从文件里读出来,都要和字符串相互转化。但这样转化太麻烦,所以在C语言中,我们可以使用sscanf和sprintf转化完后用fwrite和fread写到文件里和读取。而在c++中重载了流插入和流提取,所以也不需要自己去做转换。

class Text
{
public:Text(const char* filename = "./info.text"):_filename(filename){}void Read(A& rA){ifstream ifs(_filename);ifs >> rA._a >> rA._b >> rA._c;}void Write(){A data(1, 'a', "hello world");ofstream ofs(_filename);ofs << data._a;ofs << data._b;ofs << data._c;//可以使用getline}
private:string _filename;
};

stringstream

自定义类型不方便转为字符串,所以可以调用stringstream。

class A
{
public:A(int a=0,char b='\0', string c=""):_a(a),_b(b),_c(c){}int _a;char _b;string _c;
};ostream& operator << (ostream & os, A aa)//必要手动写格式
{os << aa._a << '/' << aa._b << '/' << aa._c;return os;
}int main()
{A tmp(20, 'a', "hello world");ostringstream oss;oss << tmp;string out = oss.str();cout << out << endl;return 0;
}

在这里插入图片描述
但stringstream并不会用于比较复杂的情景,比较复杂的情景可以使用json。

class Date
{
public:Date(int _year,int _month,int _day):year(_year),month(_month),day(_day){}int year;int month;int day;
};
istream& operator>>(istream& is, Date& d)
{is >> d.year >> d.month >> d.day;return is;
}ostream& operator<<(ostream& os, Date& d)
{os << d.year <<' ' << d.month<<' ' << d.day << ' ';return os;
}
class Parent
{
public:Parent(int a1,char b1,Date c1):a(a1),b(b1),c(c1){}int a;char b;Date c;
};ostream& operator<<(ostream& os, Parent& p)
{os << p.a <<' ' << p.b<<' ' << p.c << ' ';return os;
}istream& operator>>(istream& is, Parent& p)
{is >> p.a >> p.b >> p.c;return is;
}int main()
{Date d1(2025, 8, 16);Parent p1(10, 'a', d1);ostringstream os;os << p1;Date d2(2024, 9, 18);Parent p2(20, 'b', d2);istringstream is(os.str());is >> p2;return 0;
}
http://www.xdnf.cn/news/18167.html

相关文章:

  • 【101页PPT】芯片半导体企业数字化项目方案汇报(附下载方式)
  • ArrayList的扩容源码分析
  • 1083. 数列极差问题
  • duiLib 实现鼠标拖动标题栏时,窗口跟着拖动
  • K8s核心组件全解析
  • 产品设计.原型设计
  • 嵌入式 Linux LED 驱动开发实验
  • SpringBoot 整合 Langchain4j:系统提示词与用户提示词实战详解
  • EP1C12F324I7N Altera Cyclone FPGA
  • Python 读取 CSV 文件并删除前五列
  • [安洵杯 2019]Attack
  • Win11更新0x80073712错误解决方法
  • Java 中重载与重写的全面解析(更新版)
  • vscode的使用
  • 10.从开始写LINUX内核——时钟中断
  • 12分区南排烟机,多线模块没电
  • nflsoi 8.16 题解
  • day42_2025-08-16
  • Windows MCP.Net:基于.NET的Windows桌面自动化MCP服务器深度解析
  • 第3章现象表:比较顺序表和链表
  • 记录 GMS 认证相关条件
  • Leetcode 14 java
  • A*寻路算法:原理、实现与优化指南
  • 【Java笔记】synchronized
  • SpringBoot学习日记(九)
  • 游戏客户端性能测试总结
  • 【渗透实战】无下载器环境(curl/wget)下玩转 Metasploit 自动利用
  • [创业之路-550]:公司半年度经营分析会 - 解决方案汇总
  • “preinstall“: “npx only-allow pnpm“
  • WrenAI部署,解决发送消息报错:failed to create asking task