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

c++学习小结

内存分配

空间

栈区(stack)。编译器⾃动分配与释放,主要存放函数的参数值,局部变量值等,连续的内存空 间,由⾼地址向低地址扩展。

堆区(heap) 。由程序员分配与释放;不连续的空间,通过空闲链表进⾏连接。堆是低地址向⾼ 地址扩展,空间较⼤。频繁地分配和释放不同⼤⼩的堆空间将会产⽣堆内碎块。

静态存储区。存放全局变量和静态变量;分为全局初始化区和全局未初始化区。

常量存储区。存放常量字符串;对于全局常量,编译器⼀般不分配内存,放在符号表中以提⾼访问 效率。

程序代码区。存放函数体的⼆进制代码。

对象内存分配方式

class Base {public:Base(){cout << "Hello, world!base base" << "\n";}~Base(){cout << "Hello, world!base ~base" << "\n";}void go() {cout << "Hello, world!base go" << "\n";}
};class Player : public Base{public:Player(){cout << "Hello, world!player base" << "\n";}~Player(){cout << "Hello, world!player ~base" << "\n";}void go() {cout << "Hello, world!player" << "\n";}
};

栈空间分配

1函数结束而回收(会调用析构函数) 创建时会调用构造函数

int main()
{Base base;return 0;
}

输出

new 堆空间分配

1. 分配未初始化的内存空间(malloc)。若出现问题则抛出异常

2. 使⽤对象的构造函数进⾏初始化。若出现异常则⾃动调⽤delete释放内存

3 使用delete回收(会调用析构函数)  创建时会调用构造函数

int main()
{Base *base = new Base;base->go();delete base;return 0;
}

输出

malloc 堆空间分配

1 通过 brk() 系统调⽤从堆分配内存:如果⽤户分配的内存⼩于 128 KB,就是通过 brk() 函 数将「堆顶」指针向⾼地址移动,获得新的内存空间。free 释放内存的时候,并不会把内存归还给 操作系统,⽽是缓存在 malloc 的内存池中,待下次使⽤;

2 通过 mmap() 系统调⽤在⽂件映射区域分配内存。free 释放内存的时候,会把内存归还给 操作系统,内存得到真正的释放

3 使用free回收 

int main()
{Base *base = (Base*)malloc(sizeof(Base));base->go();free(base);return 0;
}

输出

构造函数和析构函数

class Base {public:Base(){cout << "Hello, world!base base" << "\n";}~Base(){cout << "Hello, world!base ~base" << "\n";}void go() {cout << "Hello, world!base go" << "\n";}
};

如果在栈空间分配 那么声明时就调用构造函数

函数结束时调用析构函数

如果是用new在堆空间分配

new时会调用构造函数

delete时会调用析构函数

子类和父类

class Base {public:Base(){cout << "Hello, world!base base" << "\n";}~Base(){cout << "Hello, world!base ~base" << "\n";}void go() {cout << "Hello, world!base go" << "\n";}
};class Player : public Base{public:Player(){cout << "Hello, world!player base" << "\n";}~Player(){cout << "Hello, world!player ~base" << "\n";}void go() {cout << "Hello, world!player" << "\n";}
};
int main()
{Player *player = new Player;delete player;return 0;
}

输出 可以发现构造函数是先调用父类的再调用子类的

析构函数则相反 先子类再父类的

子类实例化父类

int main()
{Base *base = new Player;base->go();delete base;return 0;
}

输出 可以看到构造函数还是会父类加子类的  但是本质上base还是Base类的对象 所以go函数调用的还是父类的接口 

析构函数调用的是父类的

虚函数

若类可能被继承,且需通过基类指针管理派生类对象,基类析构函数必须为虚函数

也就是父类想调用子类的函数 那么就使用虚函数

class Base {public:Base(){cout << "Hello, world!base base" << "\n";}virtual ~Base(){cout << "Hello, world!base ~base" << "\n";}virtual void go() {cout << "Hello, world!base go" << "\n";}
};
int main()
{Base *base = new Player;base->go();delete base;return 0;
}

输出 

可以看到构造函数还是 父类加子类的

但是go函数调用的是子类的接口

然后析构函数是子类再加父类的 因为父类的析构函数也是虚函数 

虚函数也会占用对象的内存大小

volatile、extern区别

volatile int i=10;

在cpu内核中有l1 l2 l3缓存   

每个核心拥有自己的l2 每个核心的超线程拥有自己的l1 所有核心共享l3

那么l1 和内存就有相同数据的多份拷贝

volatile的变量就是每次读就是读内存中的数据 不读l缓存的数据

extern声明的对象或者函数 表明读取全局的对象 有外部连接性 表示使用的是其他文件的对象

预处理、编译、汇编、链接

预处理阶段:预处理器根据 # 开头的命令,修改原始的程序,如把头⽂件插⼊到程序⽂本中,删除所有 的注释等。

编译阶段:编译过程就是把预处理完的⽂件进⾏⼀系列的词法分析、语法分析、语义分析等,最终产⽣ 相应的汇编语⾔⽂件,不同的⾼级语⾔翻译的汇编语⾔相同。编译是对源⽂件分别进⾏的,每个源⽂件 都产⽣⼀个⽬标⽂件。

汇编阶段:把汇编语⾔代码翻译成⽬标机器指令。

链接阶段:将有关的⽬标⽂件和库⽂件相连接,使得所有的这些⽂件成为⼀个能够被操作系统装⼊执⾏ 的统⼀整体。链接处理可分为两种: 静态链接:函数的代码将从其所在的静态链接库中被拷⻉到最终的可执⾏⽂件中。这样程序在被执 ⾏时会将其装⼊到该进程的虚拟地址空间中。

静态链接库实际上是⼀个⽬标⽂件的集合,其中的每 个⽂件含有库中的⼀个或者⼀组相关函数的代码。

动态链接:函数的代码被 放到 称作是动态链接库或共享对象的某个⽬标⽂件中。

链接程序要做的 只是在最终的可执⾏⽂件中记录下相对应的信息。在可执⾏⽂件被执⾏时,根据可执⾏程序中记录 的信息,将动态链接库的全部内容映射到相应运⾏进程的虚拟地址空间上。 对于可执⾏⽂件中的函数调⽤,可分别采⽤动态链接或静态链接的⽅法。使⽤动态链接能够使最终的可 执⾏⽂件⽐较短⼩,并且当共享对象被多个进程使⽤时能节约⼀些内存,因为在内存中只需要保存⼀份 此共享对象的代码。但并不是使⽤动态链接就⼀定⽐使⽤静态链接要优越

数据结构

数组

int arr[5] = {1, 2, 3, 4, 5};
cout << arr[0]; // 输出第一个元素

结构体

struct Person {string name;int age;
};
Person p = {"Alice", 25};
cout << p.name << endl; // 输出 Alice

stack<int> s;
s.push(1);
s.push(2);
cout << s.top(); // 输出 2
s.pop();

队列

queue<int> q;
q.push(1);
q.push(2);
cout << q.front(); // 输出 1
q.pop();

哈希表

unordered_map<string, int> hashTable;
hashTable["apple"] = 10;
cout << hashTable["apple"]; // 输出 10

映射

map<string, int> myMap;
myMap["apple"] = 10;
cout << myMap["apple"]; // 输出 10

集合

set<int> s;
s.insert(1);
s.insert(2);
cout << *s.begin(); // 输出 1

动态数组

vector<int> v;
v.push_back(1);
v.push_back(2);
cout << v[0]; // 输出 1

http://www.xdnf.cn/news/2406.html

相关文章:

  • AUTOSAR图解==>AUTOSAR_SWS_StandardTypes
  • PotPlayer,强大的高清视频播放器
  • 使用 Spring Boot 进行开发
  • TypeScript基础数据类型详解
  • 多数元素(简单)
  • VSCode远程登录云服务器并设置免密登录全攻略
  • java每日精进 4.26【多租户之过滤器及请求处理流程】
  • llama factory怎么命令行推理图片
  • java—基础
  • A. Everybody Likes Good Arrays!
  • Java 程序运行和类路径处理
  • map和set的应用总结
  • MySQL 常用语句教程
  • Python数值类型修炼手册:从青铜到王者的进阶之路
  • Buffer Pool是什么,有什么作用
  • 【MATLAB第118期】基于MATLAB的双通道CNN多输入单输出分类预测方法
  • Android学习总结之协程对比优缺点(协程一)
  • 腾讯云智三道算法题
  • 侵水防触电的原理是什么? 侵水防触电算先进技术吗?-优雅草卓伊凡
  • 【Redis——通用命令】
  • 写时拷贝讲解
  • SQL:MySQL 函数
  • Eigen库入门
  • 博客文章格式更新2.0
  • N维漂洛界的定义和参数方程
  • 算法设计课作业
  • 【概念】什么是 JWT Token?
  • JAVA多线程(8.0)
  • matlab实现稀疏低秩去噪
  • day7 python针对心脏病数据集预处理