【C/C++】知识点系统复习 (第一周)
2018/12/18 周二
1. C++内存布局分为几个区域,每个区域有什么特点?
主要可以分为 5 个区域,
(1) 栈区:由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
(2) 堆区:由程序员分配释放。
(3) 全局/静态区:全局变量和静态变量的存储是放在一块的,在程序编译时分配。
(4) 文字常量区:存放常量字符串
(5) 程序代码区:存放函数体(类的成员函数,全局函数)的二进制代码
内存布局见CSAPP第七章的图7-13,Linux运行时存储器映像
衍生问题:
1.1 栈和堆的区别
(1) 管理方式不同;(栈是系统自动分配, 堆是需要程序员申请,程序员释放,使用不好可能 memory leak)
(2) 空间大小不同;
栈是向低地址扩展的数据结构,它的容量是系统预先设定好的,一般是1M或者2M?申请的时候不要超过栈的剩余空间。
堆是向高地址扩展的数据结构,链表的方式来存储空闲内存地址的,不连续,链表遍历方向是从低地址向高地址。堆可以获得的空间受限于计算机系统中有效的虚拟内存的大小。(一般来说可以到达 4GB?)
(3) 能否产生碎片不同;(堆是链表分配内存,容易产生碎片,栈不会产生碎片)
对于堆来说,频繁的 new/delete操作势必会造成内存空间的不连续,从而造成大量的碎片,使得程序效率降低。对于栈来说,不会出现这个问题,因为栈是先进先出的。在栈顶弹出之前,永远不可能有一个内存块从栈中间弹出。
(4) 生长方向不同;(栈:高地址->低地址(生长方向向下), 堆: 低地址->高地址(生长方向向上))
(5) 分配方式不同;
内存有两种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配是用 malloc, calloc 函数进行分配,但是栈的动态分配和堆的动态分配是不同的,栈的动态分配由编译器进行释放,不需要手动。
(6) 分配效率不同;(栈:系统分配,速度快,堆:new出来的内存,速度慢)
2.当定义类的时候,编译器会自动为类自动生成那些函数?这些函数各自有什么特点?
构造函数,析构函数
3.什么是浅拷贝,什么是深拷贝?
浅拷贝是说拷贝指向空间的指针,拷贝出来的目标对象的指针和原对象的指针指向内存的同一块空间。(几个对象共用一块内存空间)
深拷贝是说拷贝对象的具体内容,其内容的地址是程序员向系统申请分配的,拷贝结束后拷贝的内容完全一样,但是使用的内存空间地址不同。
4.实现一个自定义的string类,保证main函数的正确执行。(main函数已经给出)
题解:主要是实现深拷贝情况下的构造函数和析构函数。构造函数包含无参构造函数,有参构造函数,拷贝构造函数,和赋值构造函数。析构函数可以delete开辟的堆空间。
1 /* 2 * File: string.cc 3 * Time: 2018-12-18 19:36:01 4 * Author: wyzhang 5 */ 6 7 #include <cstdio> 8 #include <cstring> 9 #include <iostream> 10 11 using std::cout; 12 using std::endl; 13 14 class String { 15 public: 16 String() 17 : _ptr(nullptr) { 18 _ptr = nullptr; 19 cout << __FUNCTION__ << endl; 20 } 21 String(const char * s) 22 : _ptr(new char[strlen(s) + 1]()) { 23 cout << "String(const char * s)" << endl; 24 strcpy(_ptr, s); 25 } 26 27 String & operator = (const char * s) { 28 cout << "String & operator = (const char * s)" << endl; 29 _ptr = new char[strlen(s) + 1](); 30 strcpy(_ptr, s); 31 } 32 33 String & operator = (const String & rhs) { 34 cout << "String & operator = (const String & rhs)" << endl; 35 if (&rhs == this) { 36 return *this; 37 } 38 _ptr = new char[strlen(rhs._ptr)+1](); 39 strcpy(_ptr, rhs._ptr); 40 } 41 String(const String & rhs) 42 : _ptr(new char[strlen(rhs._ptr) + 1]()) { 43 cout << "String(const String & rhs)" << endl; 44 strcpy(_ptr, rhs._ptr); 45 } 46 ~String() { 47 cout << "~String()" << endl; 48 if (_ptr) { 49 delete[] _ptr; 50 } 51 } 52 void print() { 53 if (!_ptr) { 54 cout << "_ptr is nullptr. " << endl; 55 return; 56 } 57 cout << "string = " << _ptr << endl; 58 } 59 private: 60 char * _ptr; 61 }; 62 int main () { 63 String str1; 64 str1.print(); 65 66 String str2 = "hello world"; 67 String str3("test"); 68 69 cout << __LINE__ << ": " ; str2.print(); 70 cout << __LINE__ << ": " ; str3.print(); 71 72 String str4 = str3; 73 cout << __LINE__ << ": " ; str4.print(); 74 75 str4 = str2; 76 cout << __LINE__ << ": " ; str4.print(); 77 78 return 0; 79 }
string.cc
5.单例模式复习
题解:感觉 singleton 还是写的有点点问题。先放着吧。这个务必学会手写。orz。
1 /* 2 * File: singleton.cc 3 * Time: 2018-12-19 10:22:18 4 * Author: wyzhang 5 */ 6 7 //要求: 在内存中只能创建一个对象 8 //1. 该对象不能是栈(全局)对象 9 //2. 该对象只能放在堆中 10 11 //应用场景: 12 //1. 直接替换任意的全局对象(变量)//因为全局对象越少越好 13 //2. 配置文件 14 //3. 词典类 15 16 //实现步骤: 17 //1. 将构造函数私有化 18 //2. 在类中定一个静态的指针对象(一般设置为私有),并且在类外初始化为空 19 //3. 定义一个返回值为类指针的静态成员函数, 20 // 如果2中的指针对象为空,则初始化对象,以后在有对象调用该静态成员函数的时候,不再初始化对象, 21 // 而是直接返回对象,保证类在内存中只有一个对象 22 23 24 #include <cstdio> 25 #include <iostream> 26 27 using std::cout; 28 using std::endl; 29 30 class Singleton { 31 public: 32 static Singleton * getInstance() { //不是静态的成员函数就没法调用,因为没有对象,需要类名调用 33 if (!_pInstance) { 34 _pInstance = new Singleton(); 35 } 36 return _pInstance; 37 } 38 static void destory() { 39 if (_pInstance) { 40 delete _pInstance; 41 } 42 } 43 void print() { 44 cout << "Singleton::print() " ; 45 if (_pInstance) { 46 printf("_pInstance = %p \n", _pInstance); 47 } 48 } 49 private: 50 Singleton() { 51 cout << "Singleton()" << endl; 52 } 53 ~Singleton() { 54 cout << "~Singleton(): " ; 55 printf("_pInstance = %p \n", _pInstance); 56 } 57 static Singleton * _pInstance; 58 }; 59 60 Singleton * Singleton::_pInstance = 0; 61 62 /* 63 wyzhang@IdeaPad:~/code/c++/20181214/homework$ ./singleton 64 Singleton() 65 p1 = 0x555eef444e70 66 p2 = 0x555eef444e70 67 Singleton::print() _pInstance = 0x555eef444e70 68 ~Singleton(): _pInstance = 0x555eef444e70 69 Singleton::print() _pInstance = 0x555eef444e70 70 ~Singleton(): _pInstance = 0x555eef444e70 71 */ 72 73 int main () { 74 Singleton * p1 = Singleton::getInstance(); 75 Singleton * p2 = Singleton::getInstance(); 76 printf("p1 = %p\n", p1); 77 printf("p2 = %p\n", p2); 78 79 p1->print(); 80 p1->destory(); 81 82 //可能写的有bug?能调用析构函数两次? 83 p2->print(); 84 p2->destory(); 85 86 return 0; 87 }
singleton.cc
6.编写一个类,实现栈操作。
编写一个类,实现简单的栈。栈中有以下操作:
> 元素入栈 void push(int);
> 元素出栈 void pop();
> 读出栈顶元素 int top();
> 判断栈空 bool emty();
> 判断栈满 bool full();
如果栈溢出,程序终止。栈的数据成员由存放10个整型数据的数组构成。先后做如下操作:
> 创建栈
> 将10入栈
> 将12入栈
> 将14入栈
> 读出并输出栈顶元素
> 出栈
> 读出并输出栈顶元素
1 /* 2 * File: stack.cc 3 * Time: 2018-12-19 11:14:15 4 * Author: wyzhang 5 */ 6 7 #include <cstdio> 8 #include <iostream> 9 #include <vector> 10 11 using std::cout; 12 using std::endl; 13 using std::vector; 14 15 class Stack { 16 public: 17 Stack() { 18 19 } 20 Stack(int n) { 21 nums.reserve(n); //capacity 22 } 23 ~Stack() { 24 nums.clear(); 25 } 26 void push(int num) { 27 if (full()) { 28 cout << "can not push, stk is full. input is " << num << endl; 29 return; 30 } 31 nums.push_back(num); 32 } 33 void pop() { 34 if (empty()) { 35 cout << "can not pop, stk is empty." << endl; 36 return; 37 } 38 nums.pop_back(); 39 } 40 int top() { 41 if (empty()) { 42 cout << "can not get top, stk is empty." << endl; 43 return -1; 44 } 45 return nums.back(); 46 } 47 bool empty() { 48 return nums.size() == 0; 49 } 50 bool full() { 51 return nums.size() == nums.capacity(); 52 } 53 private: 54 vector<int> nums; 55 }; 56 57 int main () { 58 Stack stk = Stack(2); 59 stk.push(10); 60 stk.push(12); 61 stk.push(14); 62 63 cout << "top of stk is " << stk.top() << endl; 64 stk.pop(); 65 cout << "top of stk is " << stk.top() << endl; 66 67 cout << "stk is emtpy : " << stk.empty() << endl; 68 cout << "stk is full : " << stk.full() << endl; 69 return 0; 70 }
stack.cc
7.编写一个类,实现简单队列操作
编写一个类,实现简单的队列。队列中有以下操作:
> 元素入队 void push(int);
> 元素出队 void pop();
> 读取队头元素 int front();
> 读取队尾元素 int back();
> 判断队列是否为空 bool emty();
> 判断队列是否已满 bool full();
1 /* 2 * File: queue.cc 3 * Time: 2018-12-19 11:45:10 4 * Author: wyzhang 5 */ 6 7 #include <cstdio> 8 #include <iostream> 9 #include <vector> 10 11 using std::cout; 12 using std::endl; 13 using std::vector; 14 15 class Queue { 16 public: 17 Queue() 18 : first(0) 19 , rear(0) 20 , size(0) 21 , capacity(0) { 22 } 23 Queue(int num) 24 : first(0) 25 , rear(0) 26 , size(0) 27 , capacity(num) { 28 nums.reserve(num); 29 } 30 ~Queue() { 31 nums.clear(); 32 first = rear = -1; 33 size = capacity = 0; 34 } 35 void push(int num) { 36 if (full()) { 37 cout << "can not push element, queue is full. input is " << num << endl; 38 return; 39 } 40 ++size; 41 nums[rear] = num; 42 rear = (rear + 1) % capacity; 43 } 44 void pop() { 45 if (empty()) { 46 cout << "can not pop, queue is empty." << endl; 47 return; 48 } 49 --size; 50 first = (first + 1) % capacity; 51 } 52 int front() { 53 if (empty()) { 54 cout << "can not get front, queue is empty." << endl; 55 return -1; 56 } 57 return nums[first]; 58 } 59 int back() { 60 if (empty()) { 61 cout << "can not get back, queue is empty." << endl; 62 return -1; 63 } 64 int tmp_rear = ((rear + capacity) - 1) % capacity; 65 return nums[tmp_rear]; 66 } 67 bool empty() { 68 return size == 0; 69 } 70 bool full() { 71 return size == capacity; 72 } 73 74 private: 75 vector<int> nums; 76 int first, rear, size, capacity; 77 78 void print() { 79 printf("capacity = %d, size = %d, first = %d, rear = %d, [", capacity, size, first, rear); 80 for (int i = 0; i < capacity; ++i) { 81 printf(" %d", nums[i]); 82 } 83 printf("]\n"); 84 } 85 }; 86 87 int main () { 88 Queue que = Queue(3); 89 que.push(1); 90 printf("%d: que.front = %d, que.back = %d\n", __LINE__, que.front(), que.back()); 91 que.push(2); 92 que.push(3); 93 que.push(4); 94 printf("%d: que.front = %d, que.back = %d\n", __LINE__, que.front(), que.back()); 95 que.pop(); 96 printf("%d: que.front = %d, que.back = %d\n", __LINE__, que.front(), que.back()); 97 98 printf("begin while loop\n"); 99 while (!que.empty()) { 100 printf("%d: que.front = %d, que.back = %d\n", __LINE__, que.front(), que.back()); 101 que.pop(); 102 } 103 return 0; 104 }
queue.cc
8.封装Linux下互斥锁和条件变量
9. 实现只能生成栈对象的代码
10. 实现只能生成堆对象的代码
11. 统计一篇英文(The_Holy_Bible.txt)文章中出现的单词和词频
输入:某篇文章的绝对路径
输出:词典(词典中的内容为每一行都是一个“单词 词频”)
词典的存储格式如下
-----------------
| a 66 |
| abandon 77 |
| public 88 |
| ...... |
|_________________|
class Dictionary { public: //...... void read(const std::string & filename); void store(const std::string & filename); private: //...... };
转载于:https://www.cnblogs.com/zhangwanying/p/10138282.html
【C/C++】知识点系统复习 (第一周)相关推荐
- C语言复习第一周归纳总结(简介~switch开关语句)
一.C语言简介 1. BCPL-> New B-> C-> UNIX-> Minx -> Linux->gcc C语言诞生:1971~73年,美 ...
- java面试准备之---Struts2体系知识点,系统复习,struts2原理,ognl,el支持.---随时更新
1.MVC 和 JSP Model 2 ** a.:M-Model 模型 包含两部分:业务数据和业务处理逻辑 b.V-View 视图:视图(View)的职责是负责显示界面和用户交互(收集用户信 ...
- 山东大学暑期项目实训-基于信用评分卡算法模型的个人信用评级系统的设计与实现-第一周-1(6月28日)
实训题目名称 基于信用评分卡算法模型的个人信用评级系统的设计与实现 项目流程 本项目核心信用风险评级模型的主要的研发及设计实现策略及流程如下: (1) 数据获取,包括获取存量客户及潜在客户的数据.存量 ...
- 嵌入式系统知识点 第一周 2.25
嵌入式系统知识点 第一周 2.25: 一:嵌入式开发概述: 1.嵌入式技术: 答: 在已有的硬件上移植操作系统:在操作系统之上做上层应用开发:在操作系统之下做底层开发. 2.嵌入式软件与非嵌入式软件的 ...
- 初中计算机知识点结构图,初中信息技术总复习第一课 构建知识框架
(一)设计思路: 本节课的教学内容根据课标和中考的要求,在教师的帮助下,引导学生梳理教材,构建知识框架.通过分工协作.探讨交流.归纳总结,能够构建三年来学过的知识框架,以便为后期的专项复习打下基础.在 ...
- 2017暑假 第一周 学习总结(复习)
2017暑假 学习总结目录: 1 2 3 4 Time:7.3 ~ 7.9 Content:再次认识Java,熟悉环境配置,HelloWorld 基本结构,了解开发工具 eclipse,标识符命名规范 ...
- (个人)VR实时交互的太极拳学习系统创新实训第一周(2)
这周主要进行了人物模型和示例动画的制作和利用动捕进行舞蹈学习的论文的学习. 使用Neuron和Motion Builder进行了太极拳动作的采集和处理.以下是我使用Motion Buileder导出模 ...
- 项目实训第一周2-学习系统的使用
项目实训第一周2-学习系统的使用 1.代码生成器的使用 2.sql生成器的使用 3.其他组件的使用 1.代码生成器的使用 如图,是代码生成器的基本构造 可以自行定义选择你要生成代码的注释信息,表信息, ...
- 慕课堂签到迟到怎么办_线上教学第一周:长安大学精品课程助力“云端课堂”...
课下学生点播长安大学精品在线课程视频自学,课上与老师互动解决重点难点,实现空中翻转课堂.近几年学校陆续建设了85门精品在线开放课程资源,为我校的各类课程进行大规模线上线下混合式教学积累了宝贵的实践经验 ...
最新文章
- Cheatsheet: 2013 09.10 ~ 09.21
- mysql 严格模式查看,如何查找和禁用MySQL严格模式?
- Android学习拾遗
- Saltstack_使用指南17_salt-ssh
- 阿里数据库内核月报:2015年06月
- java hibernate方言_java – 如何在运行时获取Hibernate方言
- 小型Web页打包优化(下)
- bzoj-1079 着色方案(dp)
- python之路day9_Python之路,Day7 - 面向对象编程进阶
- 函数计算机显示RAD,计算器rad是什么意思
- 视频分配器的特点以及应用
- 黑客是怎样入侵你的网站的
- java 汉语词频_java中文词频统计
- REPEATABLE-READ隔离级别 事务中无法读到其它事务提交了的最新数据
- 微分恒等式(助于找到均值、方差和其他矩)
- SAP 业务交易事件BTE(Business Transaction Event)
- 随笔 - 58, 文章 - 0, 评论 - 0, 引用 - 0 三次握手 四次握手 与socket函数的关系
- 团体程序设计天梯赛-习题集部分题解(大牛勿喷)
- 2020年防爆电气模拟考试及防爆电气实操考试视频
- Scrapy Spider中间件,你学会了吗?本篇博客有一案例