如何理解C++中的浅拷贝与深拷贝
深拷贝和浅拷贝
在进行对象拷贝时,当对象包含对其他资源的引用,如果需要拷贝这个独享所引用的对象,那就是深拷贝,否则就是浅拷贝
***
构造函数是自上而下调用,析构函数是自下而上调用
顺序
#include<iostream>
using namespace std;
class Base{
public:
Base(){cout<<"创建Base基类。"<<endl;}
~Base() {cout<<"删除Base基类。"<<endl;}
};
class Child : public Base{
public:
Child() {cout<<"创建Child派生类。"<<endl;}
~Child() {cout<<"删除Child派生类。"<<endl;}
};
int main()
{
cout<<"*********构造函数调用顺序示例***********"<<endl;
Child *C1 = new Child;
cout<<"*********析构函数调用顺序示例***********"<<endl;
delete C1;
}
基类的构造函数、析构函数不能被派生类继承
C++派生类的构造函数
C++ 标准的 new 表达式能完成大部分的需求, 但不是全部, 比如:
如何在已有的内存空间上创建对象, 标准 new 表达式做不了, C++也不支持直接在raw内存上调用对象的构造函数, 于是placement new就产生了, 取名placement, 也说明了它的历史来源, 即在原地构建一个新对象.
内存池用到placement new
linklink
***
函数模板与类模板的区别
函数模板既可以隐式调用也可以显式调用,而类模板只能显示调用
***
map内部实现了一棵红黑树,该结构具有自动排序的功能
红黑树的性质:
- 节点是红色或者黑色
- 根节点是黑色的
- 每个叶节点(NIL节点、空节点)是黑色的
- 每个红色节点的两个子节点都是黑色的(从每个叶子到根的所有路径上不能有两个连续的红色节点)
- 任一一个节点到每个叶子的所有路径都包含相同数目的黑色节点
关键性质:从根到叶子最长的可能路径不多于最短可能路径的两倍长,平衡的
红黑树的每一个节点都代表着map的一个元素。因此对map查找、添加、删除等一系列操作
所以红黑树的效率决定了map的效率
优点:效率高,很多操作在O(lgn)下就能完成;而且具有有序性
缺点:空间占用率高
unordered_map内部实现了一个hash表,所以其中的元素是乱序的
优点:查找速度非常快
缺点:hash表建立的时间比较长
***
操作对象有所不同
malloc是函数 new是关键字
new动态
malloc与free是C++/C 语言的标准库函数,new/delete 是C++的运算符。对于非内部数据类的对象而言,光用maloc/free 无法满足动态对象的要求。对象在创建的同时要自动执行构造函数, 对象消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加malloc/free。
1、new自动计算需要分配的空间,而malloc需要手工计算字节数
2、new是类型安全的,而malloc不是,比如:
int* p = new float[2]; // 编译时指出错误
int* p = malloc(2*sizeof(float)); // 编译时无法指出错误
new operator 由两步构成,分别是 operator new 和 construct
3、operator new对应于malloc,但operator new可以重载,可以自定义内存分配策略,甚至不做内存分配,甚至分配到非内存设备上。而malloc无能为力
4、new将调用constructor,而malloc不能;delete将调用destructor,而free不能。
5、malloc/free要库文件支持,new/delete则不要。
用法上也有所不同
***
预备知识:一个C/C++编译的程序占用的内存分为几个部分?
(1) 栈:由编译器自动分配释放,存放函数的参数值,局部变量的值
(2) 堆:由程序员分配,若程序员不释放可能由操作系统回收,链表
(3) 全局区(静态区):全局初始化区与全局weight初始化区
(4) 文字常量区:常量字符串
(5) 程序代码区:存放二进制代码
区别:
(1) 栈是编译器自动分配释放的,堆是程序员自己分配释放的
(2) 栈的栈顶地址与容量是系统默认设定好的,为2M,若申请的空间大于剩余的空间,则overflow,是连续的;栈向低地址生长;
堆是不连续的。堆的空间比较灵活,比较大;堆向高地址生长。
(3) 栈速度较快,堆速度较慢
(4) 在函数调用中,第一个进栈的函数调用语句的下一条可执行语句的地址--->函数的各个参数,由右向左--->函数中的局部变量
堆:堆的头部用一个字节存放堆的大小,堆中的具体内容由程序员安排
***
模板是泛型编程的基础,泛型编程即一种独立于特定类型的方式编写代码
好处:(1) 可以实现多态 (2) 代码重用
多个函数或类有着共同的操作,但是数据类型不同
类是对象的抽象,对象是类的实例;类模板是对类的抽象,类是类模板的实例
***
回调函数:通过函数指针调用的函数
把A函数的指针当作参数传给B函数,然后在B函数中通过那个指针调用A函数,A函数就是回调函数
函数指针:存储的是一个函数的地址
MFC中的定时器 SetTimer
https://blog.csdn.net/SweetTool/article/details/72811638
(1) 首先定义回调函数
(2) lambda实现回调接口并调用
***
内存泄漏:由于疏忽或者错误造成程序未能释放已经不再使用的内存的情况
http://qiusuoge.com/9820.html
https://juejin.im/entry/5808731d570c350068d5c07a
内存管理关键字与函数 new/delete malloc/free
代码逻辑
多线程
智能指针
***
https://www.cnblogs.com/chengjundu/p/8473564.html
http://www.runoob.com/design-pattern/singleton-pattern.html
设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方法
单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点
(1) 懒汉式:第一次用到类实例的时候才会去类实例化
(2) 饿汉式:在单例模式定义的时候就进行初始化
实现线程安全:懒汉式加锁,饿汉式
***
https://my.oschina.net/wangxuanyihaha/blog/183151
(8) 多线程支持
***
Qt 信号和槽机制优点效率的详解
Qt 提供了信号和槽机制用于完成界面操作的响应,是完成任意两个Qt对象之间的通信机制。
其中,信号会在某个特定情况或动作下被触发,槽是等同于接收并处理信号的函数。
优点:
1、类型安全。需要关联的信号和槽的签名必须是等同。
即信号的参数类型和参数个数 同接收该信号的槽的参数类型和参数个数相同。
2、松散耦合。信号和槽机制减弱了 Qt 对象的耦合度。
激发信号的 Qt 对象无须知道是哪个对象的哪个槽需要接收它发出的信号,它只需要做的是在适当的时间发送适当的信号就可以了,而不需要知道也不关心它的信号有没有被接收到,更不需要知道哪个对象的哪个槽接收到了信号。
同样地,对象的槽也不知道是哪些信号关联了自己,而一旦关联信号和槽,Qt 就保证了适合的槽得到了调用。即使关联的对象在运行时被删除。应用程序也不会崩溃。
效率:
信号和槽机制增强了对象间通信的灵活性,然而这也损失了一些性能。同回调函数相比,信号和槽机制运行速度有些慢。通常,通过传递一个信号来调用槽函数将会比直接调用直接调用非虚函数运行速度慢 10 倍。原因如下。
原文:https://www.cnblogs.com/jeremy0426/p/9509396.html