针织厂家东莞网站建设,zac博客seo,php连接wordpress数据库,网站开发流程详解1. 内存分析诊断工具#xff1a;valgrind#xff1b;
2. 内存管理的两种方式#xff1a; ①用户管理#xff1a;自己申请的#xff0c;自己用#xff0c;自己回收#xff1b;效率高#xff0c;但容易导致内存泄漏#xff1b; ②系统管理#xff1a;系统自动回收垃圾…1. 内存分析诊断工具valgrind
2. 内存管理的两种方式 ①用户管理自己申请的自己用自己回收效率高但容易导致内存泄漏 ②系统管理系统自动回收垃圾安全性高但消耗内存资源
3. 内存分配的两种方式
1静态分配数组存在于栈空间 ①优点物理地址连续方便遍历 ②缺点分配与利用效率较低
2动态分配malloc、new存在于堆空间 ①优点使用效率较高 ②缺点物理地址不连续
4. 防止内存泄漏的方法 ①养成良好的编码规范 ②使用指针时初始化就置空避免野指针 ③malloc后及时freenew后及时delete ④利用内存检测工具如valgrind进行辅助处理且可以利用g选项工具同步分析
5. 为什么c没有GC机制? ①没有共同的基类c从C语言演变而来可以直接操作指针且类型之间可以相互转换对于一个指针无法直到它实际指向类型 ②系统开销比较大垃圾回收带来的系统开销需要占用更多的内存违反了c的设计哲学“不为不必要的功能支付代价”不符合高效特性 ③且c中有析构函数实现智能指针通过引用计数来管理资源的释放对GC的需求不迫切
6. 智能指针 1智能指针的作用帮助开发者对动态分配的对象进行声明周期管理可以有效地防止内存泄漏 2分类可以分为三类 ①unique_ptr独占指针 ②shared_ptr共享指针 ③weak_ptr弱指针 3shared_ptr共享指针 ①共享多个指针可以同时指向同一个对象当最后一个指针被销毁或者指向其他对象时这个对象会被释放 ②工作原理内部有计数器实时记录该共同空间被几个智能指针指向其本质是对裸指针进行分装下有封装例子 ③导致引用计数增加的情况用一个智能指针初始化另一个智能指针、函数传参传递一个智能指针即复制函数返回值返回一个智能指针 ④引用计数减少的情况给智能指针赋予新值指向一个新的对象、局部的智能指针离开作用域 ⑤语法注意初始化不可以用 “ ” 号有两种初始化的方法手动初始化、函数初始化std::make_shared函数
shared_ptrintpi(new int(5)); //初始化1内部调用的构造函数
shared_ptrintpi new int(5); //错误用法
auto p std::make_sharedstring(hello world); //(初始化2)函数方法
int *p pi.get(); //获得pi的裸指针注意智能指针一旦释放裸指针也就失效
pi.reset(); //将pi置空
pi.use_count(); //返回该智能指针的引用计数
pi.reset(new int (6)); //改变pi的指向
delete p; //释放
delete p; //释放数组指针void test(shared_ptrintp) //智能指针作为形参
{}reinterpret_pointer_cast(); //可以将任意类型的指针进行转换 ⑥自定义删除器一些情况下默认删除器处理不了shared_ptr管理动态数组需要自己指定删除器下有详细例子 ⑧指针类型转换函数
static_pointer_cast //void*与裸指针转换
dynamic_pointer_cast //向下类型转型基类→派生类基类需要有虚函数
const_pointer_cast //去除裸指针的const属性
reinterpret_pointer_cast //任意类型之间裸指针转换 4unique_ptr独占指针 ①同一时刻只能有一个unique_ptr指向这个对象当指针销毁指向的对象也销毁 ②语法注意初始化不可以用 “ ” 号有两种初始化的方法手动初始化、函数初始化std::make_unique函数
unique_ptrintp(new int(5));
unique_ptrintp new int(5); //错误用法不可以使用
atuo pi std::make_uniquestring(hello world);③其他操作方法例如reset()、get()等于shared_ptr一样 5weak_ptr独占指针 ①weak_ptr是弱指针不是独立的指针不能单独操作所指向的资源 ②用处一weak_ptr辅助shared_ptr的使用监视shared_ptr 指向对象的生命周期 ③用处二weak_ptr和shared_ptr之间可以相互转换shared_ptr可以赋给weak_ptr反过来不可以 (6)自己封装的智能指针shared_ptr();
hpp:
#pragma once
#include iostream
using namespace std;
//自己封装的智能指针shared_ptr();
template typename T
class Smartpointer
{
public:template typename Ufriend class Smartpointer; //声明一种友元类Smartpointer() : m_p(nullptr){//m_p nullptr;m_count new long(0);}explicit Smartpointer(T * p) //禁止隐式转换,就是不可以使用只能使用初始化{coutexplicitendl;if(p ! nullptr){m_p p;m_count new long(1); //次数计为1}else{m_p nullptr;m_count new long(0); //次数为0}}template typename USmartpointer(T *p, SmartpointerU other) //另外一种类型U{if(p ! nullptr){m_p other.m_p;m_count other.m_count;(*m_count);}else{m_p nullptr;m_count other.m_count;}}Smartpointer(SmartpointerT other) //拷贝构造{cout拷贝构造endl;if(other.m_p ! nullptr){m_p other.m_p;m_count other.m_count;(*m_count);}else{m_p nullptr;m_count other.m_count;}}SmartpointerT operator(const SmartpointerT other) //重载{coutoperatorendl;if(other.m_p ! nullptr){m_p other.m_p;m_count other.m_count;(*m_count);}else{m_p other.m_p;m_count other.m_count;}return *this;}Smartpointer(SmartpointerTother) //移动构造{cout移动构造endl;if(other.m_p nullptr){m_p other.m_p;other.m_p nullptr;m_count other.m_count;other.m_count nullptr;}else{m_p nullptr;m_count other.m_count;}}~Smartpointer() //析构函数{if((m_p ! nullptr) (--(*m_count) 0)){cout~Smartpointerendl;delete m_p;delete m_count;}else{m_p nullptr;m_count nullptr;}}long use_count() const //函数后面加const的作用{return *m_count;}T * get() //返回裸指针{return m_p;}void reset(T *p){if(p nullptr){m_p p;(*m_count)--;m_count new long(1); //引用计数从新置为1}else{m_p nullptr;m_count new long(0);}}void reset(){m_p nullptr;(*m_count)--;}void swap(SmartpointerT other){std::swap(m_p,other.m_p); //c库内置函数实现交换std::swap(m_count,other.m_count);}T operator*(){ coutoperator*endl;return *m_p;}T * operator-(){return m_p;}operator bool(){return m_p ! nullptr;}T operator[](int index) //重载[]{return m_p[index];}template typename T1, typename U1friend SmartpointerT1 static_pointer_cast(SmartpointerU1other); //声明一种友元函数用于不同类型的智能指针转换private:T * m_p; //裸指针long * m_count; //引用计数指针
};template typename T, typename U
SmartpointerT static_pointer_cast(SmartpointerUother)
{T * temp static_castT *(other.m_p);return Smartpointer(temp,other);
}
cpp:
#include smart_pointer.hpp
#include iostream
#include stringusing namespace std;int main(int argc, char **argv)
{Smartpointerintt1(new int (5));cout(*t1)endl;coutt1.use_count()endl;Smartpointerintt2(t1);coutt2.use_count()endl;coutt1.use_count()endl;Smartpointerstringt3(new string (hello world));// Smartpointerstringt2(t4,t3);//Smartpointerint static_pointer_cast(t3); //指针类型转换没有成功Smartpointerintt4 t2;cout(*t4)endl;coutt4.use_count()endl;Smartpointerintt5(std::move(t4));return 0;
}7. 内存池 1new内存分配细节 ①new分配内存实际是调用malloc函数进行内存分配的 ②malloc实际分配内存时不单单分配需要的内存大小还要附加大量的附带内存用以记录相关使用信息包括记录分配了多少个字节占4字节、调试信息占30-60字节、边界调整占10字节、尾信息4字节也就是说除了实际分配的内存比如给一个int变量分配4字节还要附加70字节左右的附加内存内存浪费很严重尤其是频繁申请小块内存时浪费更加严重 ③重载new操作符、重载delete操作符
void *operator new(size_t size)
{int *p (int *)malloc(sizeof(int)):return *p;
}void *operator new[](size_t size)
{void *p malloc(size); //内部会有转换机制将你输入的个数乘以类型的单位字节算出来总数字节赋给sizereturn p;
}void *operator delete[](void *p)
{free(p);
}void *operator delete(void *p)
{free(p);
} ④定位newpleacement new 在已经分配的原始内存中初始化一个对象相当于从之前已经分配好的大块内存中取出一块来给新的变量使用通常应用①在硬件设备地址与c的类直接关联②容器也利用了预分配内存然后逐步使用的方法
void *p1 (void*)new char[sizeof((A))]
A *p2 new (p1)A(); //调用了无参构造函数使用的是原来p1的大块内存//自定义有参的话就可以使用A(12)带参数了 2内存池池化技术是解决内存开销问题的像线程池、内存池其内部的机理是利用链表形成大内存后面每次使用时都分配一个结点空间给变量使用 ①作用减少malloc次数就减少了对内存的浪费 ②原理用malloc分配一大块内存当后面使用要分配时从这一大块内存中一点一点分派当一大块内存快用完时再用malloc申请一大块内存然后再一点一点分配 ③嵌入式指针是借用A对象所占用的前8个字节可能是2个整型数等来充当指针当被分配时就指针后移将该部分空间分配给新变量利用内存共享实现了空间的高效利用 内存池的代码实现
#include iostreamusing namespace std;class Test
{
public:Test() default;Test(int num){m_num num;}void * operator new(size_t size){coutsize sizeendl;Test *temp;if(m_head nullptr){coutmallocendl;m_head (Test *)malloc(sizeof(Test) * 50);temp m_head;for(int i 0; i 50; i){temp-next temp 1;temp temp-next;}temp-next nullptr;}coutmemendl;temp m_head;m_head m_head-next;return m_head;}void * operator new[](size_t size){coutnew[] sizeendl;void *p malloc(size); //这里的size会自动转换为以字节为单位的大小return p;}void operator delete(void *p){Test * temp (Test *)p;temp-next m_head;m_head temp;}void operator delete[](void *p){coutdelete[]endl;free(p);}int m_t;int m_num;Test *next;static Test *m_head;
};Test * Test::m_head nullptr;int main(int argc, char **argv)
{Test *p1 new Test[10]; //这里的10指的是10个Test大小的内存delete [] p1;coutbegin:endl;Test *p2 new Test(2); //??这里是重载new为什么当做构造函数报错,因为Test(2)先构造一个对象就像int(5)先初始化一个值为5的变量Test *p3 new Test(); //为什么已添加这个就报错p3-m_num 3;p3-m_t 4;coutp3-m_num : p3-m_tendl;return 0;
}