Singleton单例
singleton只允许被实例化一次,用于组织一系列全局的函数或者变量,singleton用起来像namespace。例子:随机数产生的类、渲染器类等。
#include<iostream>
class Singleton
{
public:
Singleton(const Singleton&) = delete;//删除拷贝复制函数
static Singleton& Get()//通过Get函数来获取唯一的一个实例,其定义为static也是为了能直接用类名调用
{
return s_Instance;
}
void Function(){}//执行功能的函数
private:
Singleton() {};//不能让别人实例化,所以要把构造函数放进private
static Singleton s_Instance;//定义为static,让其唯一
};
Singleton Singleton::s_Instance;
int main()
{
Singleton::Get().Function();
Singleton& sl=singleton::Get();//命名空间就不能这样子做
sl.Function();
}
使用小的string
在release模式下面(debug模式都会在堆上分配),使用size小于16的string,不会在堆上分配内存,即不会调用new;而大于等于16的string,则会分配32bytes内存以及更多,所以16个字符是一个分界线:
#include<iostream>
void* operator new(size_t size)
{
std::cout << "Allocated: " << size << std::endl;
return malloc(size);
}
int main()
{
//debug模式都会在堆上分配
std::string longName = "hbh hbh hbh hbh ";//刚好16个字符,会在堆上分配32个bytes内存
std::string testName = "hbh hbh hbh hbh";//15个字符,栈上分配
std::string shortName = "hbh";
std::cin.get();
}
debug模式
release模式
跟踪内存分配的简易方法
我们知道一个class的new是分为三步:operator new(其内部调用malloc) 返回void*、static_cast转换为这个对象指针、构造函数。而delete则分为两步:析构函数、operator delete(内部调用free函数);
new和delete都是表达式,是不能重载的;而把它们行为往下分解则是operator new 和operator delete,是有区别的。
直接用的表达式的行为是不能变的,不能重载的,即new分解成上图的三步与delete分解成上图的两步是不能重载的。这里内部的operator new和operator delete底层其实是调用的malloc,这些内部的几步则是可以进行重载的。
//写这个函数就是说不要用standard library的operator new
//链接器实际上就会改为链接这个函数
void* operator new(size_t size)
{
std::cout << "Allocing: " << size << std::endl;
return malloc(size);
}
void operator delete(void* memory, size_t size)
{
std::cout << "Free: " << size << " bytes\n";
return free(memory);
}
struct Entity
{
int x, y, z;
};
int main()
{
{
std::string name = "hbh";
}
Entity* e = new Entity();
delete e;
std::cin.get();
}
还可以写一个简单统计内存分配的类,在每次new的时候统计分配内存,在每次delete时统计释放内存,可计算出已经分配出的总内存:
#include<iostream>
struct AllocationMertics
{
uint32_t TotalAllocated = 0;
uint32_t TotalFreed = 0;
uint32_t CurrentUsage()
{
return TotalAllocated - TotalFreed;
}
};
static AllocationMertics 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);
}
static void PrintMemoryUsage()
{
std::cout << "Memory usage: " << s_AllocationMetrics.CurrentUsage() << " bytes\n" << std::endl;
}
int main()
{
PrintMemoryUsage();
{
std::string name = "hbh";
PrintMemoryUsage();
}
std::string a = "ssssssssssssssss";
PrintMemoryUsage();
std::cin.get();
}