C++Cherno 学习笔记day20 [81]-[85] 可视化基准测试、单例模式、小字符串优化sso、跟踪内存分配、左值与右值

b站Cherno的课[81]-[85]

一、C++的可视化基准测试

chrome://tracing/

总结: cpp的计时器配合自制简易json配置写出类,将时间分析结果写入一个json文件,用chrome://tracing 这个工具进行可视化

cherno演示代码地址https://gist.github.com/TheCherno/31f135eea6ee729ab5f26a6908eb3a5e

b站大神项目地址https://github.com/GavinSun0921/InstrumentorTimer

二、C++的单例模式

单例是一个类的单一实例

单例就是外表为类形式的命名空间

当我们想要拥有应用于某种全局数据集的功能,

且我们只是想要重复使用时,单例是非常有用的

应用:
随机数生成器类
渲染器

cpp 复制代码
#include <iostream>

class Singleton
{
public:
	Singleton(const Singleton&) = delete;
	static Singleton& Get()
	{
		return s_Instance;
	}

	void Function() {}

private:
	Singleton() {}
	float m_Member = 0.0f;
	static Singleton s_Instance;
};

Singleton Singleton::s_Instance;

int main()
{
	//Singleton& instance = Singleton::Get();
	auto& instance = Singleton::Get();
	Singleton::Get().Function();
}
cpp 复制代码
#include <iostream>
// 随机数生成器类
class Random
{
public:
	Random(const Random&) = delete;
	// 单例的核心就是Get函数
	static Random& Get()
	{
		return s_Instance;
	}
	static float Float() { return Get().IFloat(); }


private:
	//internal内部的Float函数
	float IFloat() { return m_RandomGenerator; }
	Random() {}
	float m_RandomGenerator = 0.5f;
	static Random s_Instance;
};

Random Random::s_Instance;

int main()
{
	auto& random = Random::Get();
	float number = random.Float();

	std::cout << number << std::endl;
	std::cin.get();
}

一旦我有了这个单例,我可以简单地写任何数量的非静态方法并通过Get函数访问它们

或者如果我想的话,我可以删掉一层交互

(指不通过Get().来调用成员函数,而是直接写static函数来包装)

然后编写这些静态函数,在内部映射到可以访问成员数据和类的所有功能的成员函数

三、C++的小字符串优化 sso

我们不喜欢字符串的原因之一:

是它们倾向于分配内存,C++(快)\ 堆分配(慢),不好

因为我们知道创建一个标准的字符串会导致内存分配

所以很多人会尽量避免,他们会尽量减少字符串的使用

换句话说,如果你有一个非常小的字符串,你就不需使用const char*

或者试图微观管理或优化你的代码

因为这可能不会导致堆分配

cpp 复制代码
#include <iostream>
#include <string>

void* operator new(size_t size)
{
	std::cout << "Allocating " << size << " bytes\n";
	return malloc(size);
}

int main() 
{
	std::string name = "wm";
	std::cin.get();
}


小字符串优化 sso:
足够小的字符串不会导致任何堆分配,因此会使您的程序运行得更快

四、跟踪内存分配的简单方法

cpp 复制代码
#include <iostream>
#include <memory>

void* operator new(size_t size)
{
	std::cout << "Allocating " << size << " bytes\n";
	return malloc(size);
}

void operator delete(void* memory)
{
	free(memory);
}

struct Object
{
	int x, y, z;
};

int main() 
{
	{
		std::unique_ptr<Object> obj = std::make_unique<Object>();
	}
	std::string name = "wm";
	std::cin.get();
}
cpp 复制代码
#include <iostream>
#include <memory>

void* operator new(size_t size)
{
	std::cout << "Allocating " << size << " bytes\n";
	return malloc(size);
}

void operator delete(void* memory, size_t size)
{
	std::cout << "Freeing " << size << " bytes\n";
	free(memory);
}

struct Object
{
	int x, y, z;
};

int main() 
{
	{
		std::unique_ptr<Object> obj = std::make_unique<Object>();
	}
	std::string name = "wm";
	std::cin.get();
}
cpp 复制代码
#include <iostream>
#include <memory>

struct AllocationMetrics
{
	uint32_t TotalAllocated = 0;
	uint32_t TotalFreed = 0;
	uint32_t CurrentUsage() { return TotalAllocated - TotalFreed; }
};

static AllocationMetrics s_AllocationMetrics;

void* operator new(size_t size)
{
	s_AllocationMetrics.TotalAllocated += size;
	return malloc(size);
}

void operator delete(void* memory, size_t size)
{
	s_AllocationMetrics.TotalFreed += size;
	free(memory);
}

struct Object
{
	int x, y, z;
};

static void PrintMemoryUsage()
{
	std::cout << "Memory Usage: " << s_AllocationMetrics.CurrentUsage() << "bytes\n";
}

int main() 
{
	PrintMemoryUsage();
	std::string name = "wm";
	PrintMemoryUsage();
	{
		std::unique_ptr<Object> obj = std::make_unique<Object>();
		PrintMemoryUsage();
	}
	PrintMemoryUsage();
	std::cin.get();
}


Valgrind 也有一些很好的工具来跟踪内存,看看它来自哪里,如何分配等等

注:Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具

五、C++的左值与右值

移动move语义

cpp 复制代码
#include <iostream>

void PrintName(const std::string& name)
{
	std::cout << "[lvalue] " << name << std::endl;
}

void PrintName(std::string&& name)
{
	std::cout << "[rvalue] " << name << std::endl;
}

int main()
{
	std::string firstName = "Yan";
	std::string lastName = "Chernikov";

	std::string fullName = firstName + lastName;

	PrintName(fullName);
	PrintName(firstName + lastName);

	std::cin.get();
}


左值是有某种存储支持的变量,右值是临时值

左值引用仅仅接受左值,除非用const

右值引用仅仅接受右值

如果你在处理一个右值引用,,如果你能从那个临时值中偷取资源,因为它是临时的,这对优化有很大帮助

总结:
左值有地址和值,可以出现在赋值运算符左边或者右边。
右值只有值,只能出现在赋值运算符右边。&&
右值只有值,没有地址, 右值是一个优化技巧(C++),因为右值往往是临时变量的。

相关推荐
心平愈三千疾8 分钟前
学习秒杀系统-实现秒杀功能(商品列表,商品详情,基本秒杀功能实现,订单详情)
java·分布式·学习
岁忧1 小时前
(nice!!!)(LeetCode 面试经典 150 题 ) 30. 串联所有单词的子串 (哈希表+字符串+滑动窗口)
java·c++·leetcode·面试·go·散列表
SunkingYang2 小时前
MFC/C++语言怎么比较CString类型最后一个字符
c++·mfc·cstring·子串·最后一个字符·比较
界面开发小八哥2 小时前
MFC扩展库BCGControlBar Pro v36.2新版亮点:可视化设计器升级
c++·mfc·bcg·界面控件·ui开发
R-G-B2 小时前
【15】MFC入门到精通——MFC弹窗提示 MFC关闭对话框 弹窗提示 MFC按键触发 弹窗提示
c++·mfc·mfc弹窗提示·mfc关闭弹窗提示·mfc按键触发 弹窗提示
艾莉丝努力练剑2 小时前
【数据结构与算法】数据结构初阶:详解顺序表和链表(四)——单链表(下)
c语言·开发语言·数据结构·学习·算法·链表
十秒耿直拆包选手2 小时前
Qt:QCustomPlot类介绍
c++·qt·qcustomplot
珊瑚里的鱼2 小时前
第十三讲 | map和set的使用
开发语言·c++·笔记·visualstudio·visual studio
逑之2 小时前
C++笔记1:命名空间,缺省参数,引用等
开发语言·c++·笔记
berlin51512 小时前
c++判断文件或目录是否存在
c++