C++一些坑/不常用的知识点的记录

本文记录了C++编程中遇到的问题,包括输入流清空、单例模式实现、shared_ptr管理数组、Boost.ASIO的独立使用、结构体字节对齐以及避免操作系统文件API的方法。通过这些知识点,有助于理解和解决C++编程中可能遇到的难题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 1.最近在处理输入流的时候,由于输入流失败后导致了无限循环。在VS2017环境下考虑使用cin.sync()清空输入流后依旧无效。简化的大致程序如下:
int main() {
	int a;
	while (true) {
		cin >> a;
		if (cin.rdstate()) {
			cout << "input bit state:" << cin.rdstate() << endl;
			cout << "输入为非int 请重新输入!" << endl;
			cin.clear();
			cin.sync();
			//cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
		}
		else {
			cout << "input bit state:" << cin.rdstate() << endl;
			cout << a << endl;
		}
	}

查阅后,知道不同编译器对cin.sync()具体实现不同,可能VS2017的实现并不是销毁输入缓冲区,使用cin.ignore()成功清空输入流。
参考见:
https://zh.cppreference.com/w/cpp/io/ios_base/sync_with_stdio
https://blog.youkuaiyun.com/imkelt/article/details/52202002
https://www.cnblogs.com/seamusopen/p/8451883.html

  • 2.关于最近实现单例模式的一些记录和思考:
    简单的线程安全的懒汉单例模式实现:
class Test {
public:
	static Test* get_instance() {
		SomeLock();
		static Test testInstance;
		return &testInstance;
		SomeUnlock();
	}
private:
	Test() {}
	~Test(){}
};

int main() { 
	auto pt=Test::get_instance();
	//...
}

简单的饿汉单例模式实现,饿汉单例模式本身就是线程安全的:

class Test {
public:
	static Test* get_instance() {
		return &testInstance;
	}
private:
	Test() {}
	~Test() {}
private:
	static Test testInstance;
};

Test Test::testInstance;

int main() {
	auto pt=Test::get_instance();
	//...
}

1) 因为testInstance是静态变量,存储在静态区,因此保证了该对象的唯一性,而不会被实例化多次。
2) 当析构函数声明为private时,无法在栈上实例化对象,因此只能考虑通过在类的内部使用静态方式构造,或者new在堆内存中,再使用一个成员函数来释放资源如delete this;
3) 但单例模式不需要手动去释放资源(即调用析构函数)。因为它只实例化一个对象,不会在运行期产生内存泄漏。程序结束时,操作系统会自动释放进程占有的全部资源,包括内存资源。

  • 3.shared_ptr<T>管理数组时,需要为数组提供一个专用的删除器,如:
shared_ptr<uint8_t> spData=make_shared<uint8_t>(new uint8_t[dataLen],[](uint8_t* p){delete[] p;});
  • 4.Boost库单独使用ASIO模块时,可以使用asio下"config.hpp"中的一些宏,如ASIO_STANDALONE、ASIO_HAS_STDARR等宏,来避免使用boost的一些基础组件,导致程序体积过大。

  • 5.结构体中的 char xx[0]是不占字节的,如sizeof(TestPack)==4:

#pragma pack(1)
typedef struct tagTestPack {
	int num;
	char data[0];
} TestPack;
#pragma pack()

记得#pragma pack(1)后还原为原来的对齐方式,同时可以使用#pragma pack(push,x)/#pragma pack(pop)。

  • 6.尽量避免依赖操作系统的文件API,在C++17中有文件系统filesystem库。同时可以如下获取文件内容文件长度:
ifstream ifs("file_path", ios::binary);
	if (!ifs) {
		cout << "Could not open file!" << endl;
	}
	//获得长度
	ifs.seekg(0, ios::end);//指针移动到文件末尾
	streampos pos = ifs.tellg();//返回指针到文件头的距离 即文件大小
	int fileLen = pos;
	cout << "File size: " << fileLen << endl;
	ifs.seekg(0);//返回文件头
	//ifs.seekg(0,ios::beg);//返回文件头
	char* srcData = new char[fileLen]();
	ifs.read(srcData,fileLen);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值