为什么析构函数必须是虚函数?为什么C++默认的析构函数不是虚函数?

references:

nowcoder

将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们new一个子类,然后使用基类指针指向该子类对象,释放基类指针时可以释放掉子类的空间,防止内存泄漏

C++默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存。而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存。因此C++默认的析构函数不是虚函数,而是只有当需要当作父类时,设置为虚函数。

函数指针

references:

nowcoder

1、定义:

函数指针是一个指向具体的函数的指针变量。

C++在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。

2、用途:

调用函数和做函数的参数,比如回调函数。

void sort(int a[], bool (p)(int ,int)){}

void (
fp)(int ,int) = cmp;

fork函数

references:

简述C语言fork()函数用法:


nowcoder

Ps.因为Windows是单用户系统(DOS),所以只能去UNIX/LInux系统上才能使用这个函数。

C++的fork函数用来创建主进程的子进程。子进程从父进程的fork()开始往下运行。在子进程中,成功的fork( )调用会返回0。在父进程中fork( )返回子进程的pid。如果出现错误,fork( )返回一个负值。

fork()

fork()

fork()

cout << 1 <<endl;

以上返回8个1。

用法:

1、一个父进程希望复制自己,使父子进程同时执行不同的代码段。

比如在网络服务程序中,父进程等待客户端的服务请求。当请求到达时,父进程调用fork()使子进程处理此请求;而父进程继续等待下一个请求。

2.、一个进程要执行一个不同的程序。

这个在shell下比较常见,这种情况下,fork()之后一般立即接exec函数。

析构函数

references:

nowcoder

不能带任何参数,也没有返回值。

如果一个类中有指针,且在使用的过程中动态的申请了内存,那么最好显示构造析构函数在销毁类之前,释放掉申请的内存空间,避免内存泄漏。

类析构顺序:1)派生类本身的析构函数;2)对象成员析构函数;3)基类析构函数。

静态函数和虚函数的区别

references:

nowcoder

静态函数在编译的时候就已经确定运行时机,虚函数在运行的时候动态绑定。

虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销。

重载,重写,隐藏

references:

C++中重载、重写(覆盖)和隐藏的区别


重载:两个函数名相同,但是参数列表不同(个数,类型),返回值类型没有要求。

重写:派生类中存在重新定义的函数。其函数名,参数列表,返回值类型,所有都必须同基类中被重写的函数一致。基类中被重写的函数必须是虚函数。

隐藏:派生类的函数屏蔽了与其同名的基类函数注意只要同名函数,不管参数列表是否相同,基类函数都会被隐藏。

如果派生类一定要使用基类的被隐藏函数,可以void f() { Base::f(); }调用。

strcpy和strlen

references:

nowcoder

strcpy是字符串拷贝函数,原型:

char *strcpy(char* dest, const char *src);

从src逐字节拷贝到dest,直到遇到'\0'结束,因为没有指定长度,可能会导致拷贝越界,造成缓冲区溢出漏洞,安全版本是strncpy函数。

strlen函数是计算字符串长度的函数,返回从开始到'\0'之间的字符个数。

虚函数和多态

references:

nowcoder

多态的实现主要分为静态多态和动态多态,静态多态主要是重载,在编译的时候就已经确定;动态多态是用虚函数机制实现的,在运行期间动态绑定。

虚函数的实现:在有虚函数的类中,类的最开始部分是一个虚函数表的指针,这个指针指向一个虚函数表,表中放了虚函数的地址,实际的虚函数在代码段(.text)中。当子类继承了父类的时候也会继承其虚函数表,当子类重写父类中虚函数时候,会将其继承到的虚函数表中的地址替换为重新写的函数地址。使用了虚函数,会增加访问内存开销,降低效率。

++i和i++的实现

写一个函数在main函数执行前先运行

全局变量可以在main函数之前调用析构函数。

static int _ = []{

cin.sync_with_stdio(false);

return 0;

}();

__attribute((constructor))是gcc扩展,标记这个函数应当在main函数之前执行。同样有一个__attribute((destructor)),标记函数应当在程序结束之前(main结束之后,或者调用了exit后)执行;

__attribute((constructor))void before()

{

printf("before main\n");

}

const char * arr = "123"; char * brr = "123"; const char crr[] = "123"; char drr[] = "123";的区别

references:

若干C/C++题目

常量字符串、常量字符数组。

C++里是怎么定义常量的?常量存放在内存的哪个位置?

常量在C++里的定义就是一个top-level const加上对象类型,常量定义必须初始化。

对于局部对象,常量存放在栈区,对于全局对象,常量存放在全局/静态存储区。对于字面值常量,常量存放在常量存储区。

const修饰成员函数的目的

const修饰的成员函数表明函数调用不会对对象做出任何更改。

shared_ptr的实现

#include<iostream>
using namespace std; template<class T>
class Shared_ptr{
public:
Shared_ptr() : ptr(nullptr), u_count(0){}
Shared_ptr(T* obj) : ptr(obj), u_count(new int(1)){}
Shared_ptr(const Shared_ptr &obj) : ptr(obj.ptr), u_count(&(++(*obj.u_count))){}
~Shared_ptr(){
--(*u_count);
if(*u_count == 0 && ptr){
delete u_count;
delete ptr;
}
}
Shared_ptr& operator = (Shared_ptr &o);
T& operator * ();//解引用
int use_count();
private:
T* ptr;
int* u_count;
}; template<class T>
Shared_ptr<T>& Shared_ptr<T>::operator = (Shared_ptr &o){
if(this == &o){ //特别注意
return *this;
}
++*o.u_count;
--this->u_count;
if(this->u_count == 0){
delete this->ptr;
delete this->u_count;
}
this->ptr = o.ptr;
this->u_count = o.u_count; return *this;
} template<class T>
T& Shared_ptr<T>::operator * (){
if(u_count == 0) return nullptr;
return *ptr;
} template<class T>
int Shared_ptr<T>::use_count(){
return *u_count;
} class A{
public:
A(){}
~A(){}
};
int main(){
Shared_ptr<A> a(new A());
cout << a.use_count() << endl;
Shared_ptr<A> b = a;
cout << b.use_count() << endl;
Shared_ptr<A> c(b);
cout << c.use_count() << endl;
return 0;
}

class与typename的区别

references:

c++中模板使用时候typename和class的区别

template<class T>

void MyMethod( T myarr )

{

typedef typename T::LengthType LengthType;

LengthType length = myarr.GetLength;

}

此时,如果没有typename,那么编译器会认为T::LengthType是T类的一个静态变量,加了之后他会认为T::LengthType是一个类型名称。

C++ part2的更多相关文章

  1. Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级

    Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 3.安装Clus ...

  2. Linux平台 Oracle 11gR2 RAC安装Part2:GI安装

    三.GI(Grid Infrastructure)安装 3.1 解压GI的安装包 3.2 安装配置Xmanager软件 3.3 共享存储LUN的赋权 3.4 使用Xmanager图形化界面安装GI 3 ...

  3. Hadoop入门学习笔记---part2

    在<Hadoop入门学习笔记---part1>中感觉自己虽然总结的比较详细,但是始终感觉有点凌乱.不够系统化,不够简洁.经过自己的推敲和总结,现在在此处概括性的总结一下,认为在准备搭建ha ...

  4. 小课堂week13 Clean Code Part2

    Clean Code Part2 对象与数据结构 首先让我们进行一个严肃的思考,对象与数据结构的区别在哪里? 如下两段代码分别用数据结构和对象的方法来描述了一个Point. public class ...

  5. K2 Blackpearl开发技术要点(Part2)

    转:http://www.cnblogs.com/dannyli/archive/2012/09/14/2685282.html K2 Blackpearl开发技术要点(Part2)  

  6. 小课堂Week9 例外处理设计的逆袭Part2

    小课堂Week9 例外处理设计的逆袭Part2 今天继续阅读<例外处理设计的逆袭>这本书,我们先看两个案例: 案例1 问:如果要设计一个依据学号到数据库中查询学生资料的函数,当找不到符合条 ...

  7. 《数字图像处理原理与实践(MATLAB版)》一书之代码Part2

    本文系<数字图像处理原理与实践(MATLAB版)>一书之代码系列的Part2(P43~80),代码运行结果请參见原书配图,建议下载代码前阅读下文: 关于<数字图像处理原理与实践(MA ...

  8. Linux平台 Oracle 12cR2 RAC安装Part2:GI配置

    Linux平台 Oracle 12cR2 RAC安装Part2:GI配置 三.GI(Grid Infrastructure)安装 3.1 解压GI的安装包 3.2 安装配置Xmanager软件 3.3 ...

  9. 自动化测试 Appium之Python运行环境搭建 Part2

    Appium之Python运行环境搭建 Part2 by:授客 QQ:1033553122 实践环境 参见 Appium之Python运行环境搭建 Part1 环境部署 1.安装Android SDK ...

  10. Linux平台 Oracle 18c RAC安装Part2:GI配置

    三.GI(Grid Infrastructure)安装 3.1 解压GI的安装包 3.2 安装配置Xmanager软件 3.3 共享存储LUN的赋权 3.4 使用Xmanager图形化界面配置GI 3 ...

随机推荐

  1. 如何封装Promise对象?

    最近看到了一个有趣的Promise的方法,这里记录下来 <script> class MyPromise { constructor(executor) { // 初始化state赋值为p ...

  2. Py-解决粘包现象,tcp实现并发,tcp实现传输文件的程序,校验思路,线程与进程

    黏包现象 TCP粘包就是指发送方发送的若干包数据到达接收方时粘成了一包,从接收缓冲区来看,后一包数据的头紧接着前一包数据的尾,出现粘包的原因是多方面的,可能是来自发送方,也可能是来自接收方TCP接收到 ...

  3. Win2008 server R2重置登录密码Administrator

    1.PE方式修改密码 背景:https://www.cnblogs.com/Crazy-Liu/p/11245730.html 上述连接中的有AD域的机器系统使用哑巴式老毛桃等启动PE出现以下: 原因 ...

  4. Linux内存 free 详解

    在Linux下,使用top命令看到内存占用情况:   Mem:  4146788k total, 3825536k used, 321252k free, 213488k buffers Swap: ...

  5. 对话 CTO〡用声音在一起,听荔枝 CTO 丁宁聊 UGC 声音互动平台的技术世界 原创 王颖奇 极客公园 2018-12-01

    https://mp.weixin.qq.com/s/jfHFXZpzbAEbHKkCMSev6w 对话 CTO〡用声音在一起,听荔枝 CTO 丁宁聊 UGC 声音互动平台的技术世界 原创 王颖奇 极 ...

  6. 编码占用的字节数 1 byte 8 bit 1 sh 1 bit 中文字符编码 2. 字符与编码在程序中的实现 变长编码 Unicode UTF-8 转换 在网络上传输 保存到磁盘上 bytes

    小结: 1.UNICODE 字符集编码的标准有很多种,比如:UTF-8, UTF-7, UTF-16, UnicodeLittle, UnicodeBig 等: 2 服务器->网页 utf-8 ...

  7. Python基础(列表中变量与内存关系)

    在Python中,copy的是内存地址,引用的是列表的引用地址,列表里存的是各个元素的地址 例如: name = [1,2,3,4,['xfxing','summer',6]] n2 = name.c ...

  8. MySql(三)存储过程和函数

    MySql(三)存储过程和函数 一.什么是存储过程和函数 二.存储过程和函数的相关操作 一.什么是存储过程和函数 存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程和函数 ...

  9. java架构《并发编程框架篇 __Disruptor》

    Disruptor入门   获得Disruptor 可以通过Maven或者下载jar来安装Disruptor.只要把对应的jar放在Java classpath就可以了. 基本的事件生产和消费 我们从 ...

  10. 全局负载均衡与CDN内容分发

    CDN简介 CDN的全称是Content Delivery Network,即内容分发网络.CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡.内容分发. ...