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开辟的堆空间。

 /*
* File: string.cc
* Time: 2018-12-18 19:36:01
* Author: wyzhang
*/ #include <cstdio>
#include <cstring>
#include <iostream> using std::cout;
using std::endl; class String {
public:
String()
: _ptr(nullptr) {
_ptr = nullptr;
cout << __FUNCTION__ << endl;
}
String(const char * s)
: _ptr(new char[strlen(s) + ]()) {
cout << "String(const char * s)" << endl;
strcpy(_ptr, s);
} String & operator = (const char * s) {
cout << "String & operator = (const char * s)" << endl;
_ptr = new char[strlen(s) + ]();
strcpy(_ptr, s);
} String & operator = (const String & rhs) {
cout << "String & operator = (const String & rhs)" << endl;
if (&rhs == this) {
return *this;
}
_ptr = new char[strlen(rhs._ptr)+]();
strcpy(_ptr, rhs._ptr);
}
String(const String & rhs)
: _ptr(new char[strlen(rhs._ptr) + ]()) {
cout << "String(const String & rhs)" << endl;
strcpy(_ptr, rhs._ptr);
}
~String() {
cout << "~String()" << endl;
if (_ptr) {
delete[] _ptr;
}
}
void print() {
if (!_ptr) {
cout << "_ptr is nullptr. " << endl;
return;
}
cout << "string = " << _ptr << endl;
}
private:
char * _ptr;
};
int main () {
String str1;
str1.print(); String str2 = "hello world";
String str3("test"); cout << __LINE__ << ": " ; str2.print();
cout << __LINE__ << ": " ; str3.print(); String str4 = str3;
cout << __LINE__ << ": " ; str4.print(); str4 = str2;
cout << __LINE__ << ": " ; str4.print(); return ;
}

string.cc

5.单例模式复习

题解:感觉 singleton 还是写的有点点问题。先放着吧。这个务必学会手写。orz。

 /*
* File: singleton.cc
* Time: 2018-12-19 10:22:18
* Author: wyzhang
*/ //要求: 在内存中只能创建一个对象
//1. 该对象不能是栈(全局)对象
//2. 该对象只能放在堆中 //应用场景:
//1. 直接替换任意的全局对象(变量)//因为全局对象越少越好
//2. 配置文件
//3. 词典类 //实现步骤:
//1. 将构造函数私有化
//2. 在类中定一个静态的指针对象(一般设置为私有),并且在类外初始化为空
//3. 定义一个返回值为类指针的静态成员函数,
// 如果2中的指针对象为空,则初始化对象,以后在有对象调用该静态成员函数的时候,不再初始化对象,
// 而是直接返回对象,保证类在内存中只有一个对象 #include <cstdio>
#include <iostream> using std::cout;
using std::endl; class Singleton {
public:
static Singleton * getInstance() { //不是静态的成员函数就没法调用,因为没有对象,需要类名调用
if (!_pInstance) {
_pInstance = new Singleton();
}
return _pInstance;
}
static void destory() {
if (_pInstance) {
delete _pInstance;
}
}
void print() {
cout << "Singleton::print() " ;
if (_pInstance) {
printf("_pInstance = %p \n", _pInstance);
}
}
private:
Singleton() {
cout << "Singleton()" << endl;
}
~Singleton() {
cout << "~Singleton(): " ;
printf("_pInstance = %p \n", _pInstance);
}
static Singleton * _pInstance;
}; Singleton * Singleton::_pInstance = ; /*
wyzhang@IdeaPad:~/code/c++/20181214/homework$ ./singleton
Singleton()
p1 = 0x555eef444e70
p2 = 0x555eef444e70
Singleton::print() _pInstance = 0x555eef444e70
~Singleton(): _pInstance = 0x555eef444e70
Singleton::print() _pInstance = 0x555eef444e70
~Singleton(): _pInstance = 0x555eef444e70
*/ int main () {
Singleton * p1 = Singleton::getInstance();
Singleton * p2 = Singleton::getInstance();
printf("p1 = %p\n", p1);
printf("p2 = %p\n", p2); p1->print();
p1->destory(); //可能写的有bug?能调用析构函数两次?
p2->print();
p2->destory(); return ;
}

singleton.cc

6.编写一个类,实现栈操作。

编写一个类,实现简单的栈。栈中有以下操作:

> 元素入栈 void push(int);

> 元素出栈 void pop();

> 读出栈顶元素 int top();

> 判断栈空 bool emty();

> 判断栈满 bool full();

如果栈溢出,程序终止。栈的数据成员由存放10个整型数据的数组构成。先后做如下操作:

> 创建栈

> 将10入栈

> 将12入栈

> 将14入栈

> 读出并输出栈顶元素

> 出栈

> 读出并输出栈顶元素

 /*
* File: stack.cc
* Time: 2018-12-19 11:14:15
* Author: wyzhang
*/ #include <cstdio>
#include <iostream>
#include <vector> using std::cout;
using std::endl;
using std::vector; class Stack {
public:
Stack() { }
Stack(int n) {
nums.reserve(n); //capacity
}
~Stack() {
nums.clear();
}
void push(int num) {
if (full()) {
cout << "can not push, stk is full. input is " << num << endl;
return;
}
nums.push_back(num);
}
void pop() {
if (empty()) {
cout << "can not pop, stk is empty." << endl;
return;
}
nums.pop_back();
}
int top() {
if (empty()) {
cout << "can not get top, stk is empty." << endl;
return -;
}
return nums.back();
}
bool empty() {
return nums.size() == ;
}
bool full() {
return nums.size() == nums.capacity();
}
private:
vector<int> nums;
}; int main () {
Stack stk = Stack();
stk.push();
stk.push();
stk.push(); cout << "top of stk is " << stk.top() << endl;
stk.pop();
cout << "top of stk is " << stk.top() << endl; cout << "stk is emtpy : " << stk.empty() << endl;
cout << "stk is full : " << stk.full() << endl;
return ;
}

stack.cc

7.编写一个类,实现简单队列操作

编写一个类,实现简单的队列。队列中有以下操作:

> 元素入队 void push(int);

> 元素出队 void pop();

> 读取队头元素 int front();

> 读取队尾元素 int back();

> 判断队列是否为空 bool emty();

> 判断队列是否已满 bool full();

 /*
* File: queue.cc
* Time: 2018-12-19 11:45:10
* Author: wyzhang
*/ #include <cstdio>
#include <iostream>
#include <vector> using std::cout;
using std::endl;
using std::vector; class Queue {
public:
Queue()
: first()
, rear()
, size()
, capacity() {
}
Queue(int num)
: first()
, rear()
, size()
, capacity(num) {
nums.reserve(num);
}
~Queue() {
nums.clear();
first = rear = -;
size = capacity = ;
}
void push(int num) {
if (full()) {
cout << "can not push element, queue is full. input is " << num << endl;
return;
}
++size;
nums[rear] = num;
rear = (rear + ) % capacity;
}
void pop() {
if (empty()) {
cout << "can not pop, queue is empty." << endl;
return;
}
--size;
first = (first + ) % capacity;
}
int front() {
if (empty()) {
cout << "can not get front, queue is empty." << endl;
return -;
}
return nums[first];
}
int back() {
if (empty()) {
cout << "can not get back, queue is empty." << endl;
return -;
}
int tmp_rear = ((rear + capacity) - ) % capacity;
return nums[tmp_rear];
}
bool empty() {
return size == ;
}
bool full() {
return size == capacity;
} private:
vector<int> nums;
int first, rear, size, capacity; void print() {
printf("capacity = %d, size = %d, first = %d, rear = %d, [", capacity, size, first, rear);
for (int i = ; i < capacity; ++i) {
printf(" %d", nums[i]);
}
printf("]\n");
}
}; int main () {
Queue que = Queue();
que.push();
printf("%d: que.front = %d, que.back = %d\n", __LINE__, que.front(), que.back());
que.push();
que.push();
que.push();
printf("%d: que.front = %d, que.back = %d\n", __LINE__, que.front(), que.back());
que.pop();
printf("%d: que.front = %d, que.back = %d\n", __LINE__, que.front(), que.back()); printf("begin while loop\n");
while (!que.empty()) {
printf("%d: que.front = %d, que.back = %d\n", __LINE__, que.front(), que.back());
que.pop();
}
return ;
}

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:
//......
};

【C/C++】知识点系统复习 (第一周)的更多相关文章

  1. 20145127 《Java程序设计》第一周学习总结

    通过第一周的Java程序设计的学习,听了娄老师的第一堂课,虽然课堂上老师并没有一开始就讲许多专业的知识,而是带领着我们对于Java这门语言,并不仅仅是一门语言,经行了初步的认识与了解,并且对于Java ...

  2. 20135328信息安全系统设计基础第一周学习总结(Linux应用)

    学习计时:共xxx小时 读书: 代码: 作业: 博客: 一.学习目标 1. 能够独立安装Linux操作系统   2. 能够熟练使用Linux系统的基本命令   3. 熟练使用Linux中用户管理命令/ ...

  3. 第一周嵌入式程序设计(linux环境下)的学习总结

    2014025641 <嵌入式程序设计>第1周学习总结 本周学习内容 首先我们先复习下之前学习过的内容,什么是linux? Linux 就是一个操作系统,就像你多少已经了解的 Window ...

  4. 《Java程序设计》第一周学习总结

    20145224 <Java程序设计>第一周学习总结 教材学习内容总结 通过第一周的学习让我对Java有了个初步的了解,知道了Java分为Java SE.Java EE.Java ME三大 ...

  5. 20145210 《Java程序设计》第一周学习总结

    教材学习内容总结 第一章: 1.Java三大平台,JavaSE的四个组成部分 Java根据应用领域的不同,区分为Java SE.Java EE.Java ME三大平台. 各应用平台的基础:Java S ...

  6. 20175221 2018-2019-2 《Java程序设计》第一周学习总结

    20175221 2018-2019-2 <Java程序设计>第一周学习总结 教材学习内容总结 本周通过观看书本配套视频,学到了如解释器,编译器等一些简单概念. 还懂得了java的一些简单 ...

  7. C语言-第一周作业

    要求1: 请在你的PC或者移动设备上安装词典,该词典工具能对计算机术语进行翻译.需要在你的博客中给出安装软件的截图,请确保阅读者能从截图判断出你的被安装的设备是PC或者移动设备.(5经验值) 要求2: ...

  8. Linux内核设计(第一周)——从汇编语言出发理解计算机工作原理

    Linux内核设计(第一周)——从汇编语言出发理解计算机工作原理 计算机工作原理 汇编指令 C语言代码汇编分析 by苏正生 原创作品转载请注明出处 <Linux内核分析>MOOC课程htt ...

  9. Java第一周学习总结5311

    20145311 <Java程序设计>第1周学习总结 教材学习内容总结 第一章1.1java的历史:总的来说,Java经历了许许多多版本的变迁,目前已经成为一种经常使用的计算机编程语言.J ...

随机推荐

  1. hibernate批量写入

    public int insertChanDaoTaskModel(List<T> t) { // TODO Auto-generated method stub Session sess ...

  2. spring @Query使用对象参数

    @Transactional @Modifying @Query(value = "UPDATE az_news a SET a.news_content =:#{#news.newsCon ...

  3. bzoj4036 [HAOI2015]按位或 状压DP + MinMax 容斥

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4036 题解 变成 \(2^n-1\) 的意思显然就是每一个数位都出现了. 那么通过 MinMa ...

  4. extjs6.0 treepanel设置展开和设置选中

    var treePanel = { id: "treeUrl", xtype: "treepanel", useArrows: true, // 节点展开+,- ...

  5. STM32 通用定时器好文章收藏

    https://blog.csdn.net/fengshuiyue/article/details/79150724 单片机入门学习十三 STM32单片机学习十 通用定时器 里面写的挺不错,图文并茂, ...

  6. docker 运行jenkins及vue项目与springboot项目(三.jenkins的使用及自动打包vue项目)

    docker 运行jenkins及vue项目与springboot项目: 一.安装docker 二.docker运行jenkins为自动打包运行做准备 三.jenkins的使用及自动打包vue项目 四 ...

  7. oracle11g笔记

    安装 #!/bin/bash #安装oracle110203 pageDir="/opt/tools/oracle" bdFile="/tmp/bdFile.txt&qu ...

  8. jQuery积累:serialize()、stringify()、toJSON()

    *)表单serialize()序列化,和serializeArray() ##)应用场景 当Ajax或者get请求发送表单中的某一个,或者某几个值到后台时,通过jQuery就能获取到这些值.然后作为A ...

  9. jquery 自定义类

    jQuery自定义类封装: (function ($) { $.DragField = function (arg) { var name = "你好"; //这个是私有变量,外部 ...

  10. 资源-DotNet-站点:DotNet 站点列表

    ylbtech-资源-DotNet-站点:DotNet 站点列表 1.ASP.NET Web返回顶部 1.1.问卷星 https://www.wjx.cn/sample/service.aspx 1. ...