WHCSRL 技术网

C++基础知识大全_clw

秋招基本尘埃落定了,打算总结一下C++学习路线的相关知识,今天是第一篇:C++基础知识总结。

面向对象的三大特性:

封装:把客观事物抽象为类,包含自己的属性和方法。
继承:使用现有类的所有功能,在无需重新编写原有类的情况下对类的功能进行拓展。被继承的类成为父类或基类,继承的类成为子类或派生类。
多态:一种形式,多种状态,分为静态多态和动态多态。静态多态指编译时多态,如函数重载、模板;动态多态指运行时多态,特指virtual虚函数机制形成的多态。
  • 1
  • 2
  • 3

类的访问权限:private、protected、public

类中可以直接访问自己类的public、protected、private成员,但类对象只能访问自己类的public成员。
  • 1

在这里插入图片描述

类的构造函数、析构函数、赋值函数、拷贝构造函数

构造函数:一个类对象创建时自动调用的方法,用来完成初始化得工作。
析构函数:当类对象生命周期结束时,自动销毁对象占有的内存。
拷贝构造函数:参数为类的引用,即用一个类对象复制构造一个新的类对象。
赋值函数:将一个类对象成员的值赋给当前对象。
  • 1
  • 2
  • 3
  • 4

一个类会自定义默认构造函数、默认拷贝构造函数、默认赋值函数、析构函数。

移动构造函数与拷贝构造函数的区别

拷贝构造函数的形参是一个左值引用,而移动构造函数的形参是一个右值引用
拷贝构造函数完成的是整个对象或变量的拷贝,而移动构造函数是生成一个指针指向源对象或变量的地址,接管源对象的内存,相对于大量数据的拷贝节省时间和内存空间。
  • 1
  • 2

深拷贝与浅拷贝的区别

浅拷贝:

利用类提供的默认拷贝构造函数,将一个对象的成员所在内存的数据复制给另一个对象的成员。
  • 1

深拷贝:

显式定义类的拷贝构造函数,不仅会将原对象的成员变量复制给新对象,还会在堆中为新对象分配一块新的内存,并将原对象持有的动态内存资源也拷贝过来。
  • 1

空类有哪些函数?空类的大小?

一个空类包括默认构造函数、拷贝构造函数、默认赋值运算符、默认取值运算符、析构函数。
空类也可以实例化,在内存会有独一无二的地址,编译器规定空类的大小为1字节;
仅含有一个虚函数的类的大小为4字节,因为虚表指针占有4个字节地址。
  • 1
  • 2
  • 3

C++内存分区

全局区:存储全局变量和静态变量,编译时分配,存在整个程序运行期间。
堆区:程序员手动管理的内存区间,运行时分配,手动开辟、释放内存。
栈区:存储局部变量,运行时分配,系统自动管理内存的开辟和释放。
常量区:存放常量,编译时分配,存在整个程序运行期间。
代码区:存放程序运行的cpu指令,编译时分配,系统自动管理内存的开辟和释放。
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述

堆区与栈区的对比

申请方式:栈区内存由系统自动管理,堆区内存由程序员手动管理。
空间大小:栈区的大小一般为1M或2M,不超过10M;堆区的大小是不固定的,受硬件内存的限制。
申请效率:栈是线性存储的,由系统自动分配,速度较快;堆区通过一个链表管理空闲内存,容易造成内存泄漏。
生长方向:栈区是由高到低的,堆区是由低到高的。
  • 1
  • 2
  • 3
  • 4

C++与C的区别

C++是面向对象的编程语言,C是面向过程的结构化编程语言。
C++采用new/delete运算符动态管理内存,而C用malloc/free库函数管理内存。
C++提供了class,C提供了struct。在C++中使用struct与class等同。
C++有引用,而C没有。
C++提供了很多输入输出流,如:iostream、ofstream。
  • 1
  • 2
  • 3
  • 4
  • 5

extern C作用

指示编译器这部分代码按照C语言的方式进行编译。如:C语言不提供函数重载,为避免重载,可使用extern C。
  • 1

C语言为啥可以重载?C++为啥不支持重载?

C语言中,函数在编译后的代码名称为“_函数名”,当同名的函数参数不同时,编译器无法解析到它们的不同,
  • 1

因为它们的编译名称都相同。
C++中,函数参数不同对象的编译后的名称也不同,所以支持重载。
在这里插入图片描述

struct与class的区别

struct在C中,不能定义函数、没有访问权限的设定,只能定义数据成员变量;在C++中,与class类似,可以定义函数、实现继承以及多态,以及有public、protected、private三种访问权限。
C++中,struct与class的唯一区别是 :

 struct中成员默认的访问权限是public,class中成员默认的访问权限是private。
  • 1

struct内存对齐

 结构体中各成员变量的首地址必须是“对齐系数”和“变量大小”的较小值的整数倍;
 结构体占用内存的总大小是“对齐系数”和“最大变量长度”的较小值的整数倍。
  • 1
  • 2

define宏定义与const常量的区别

处理时机不同:宏定义是“编译时”概念,在预处理阶段展开,生命周期结束于编译时期;const是“运行时”概念,在程序运行时使用。
存储方式不同:宏定义直接替换,不会分配内存,存储在程序的代码区中;const变量需要进行内存分配。
类型和安全检查不同:宏定义是字符替换,没有数据类型的区别,没有类型安全检查;const是常量的声明,有类型区别,编译时会进行安全检查。
  • 1
  • 2
  • 3

new/delete与malloc/free的区别

malloc是C语言定义的库函数,new是C++定义的运算符;
malloc由程序员指定分配内存的大小,而new由编译器自动计算指定类型的内存大小;
new会调用构造函数,并返回对象内存大小,malloc不会;
malloc返回类型是void*指针,需要强转换,new的返回类型是对象类型的指针;
malloc不能重载,new可以重载operator new。
  • 1
  • 2
  • 3
  • 4
  • 5

new一个对象可以用free释放内存嘛?

不可以。new一个对象,delete时会先调用类的析构函数再释放内存,而free仅仅释放内存,会出现错误。
  • 1

内存泄露的情况

 new一块内存,没有手动delete,会造成内存泄漏;
 使用智能指针shared_ptr时,产生循环引用,导致内存无法释放,会造成内存泄漏;
 类的继承中,用一个基类指针指向父类或子类对象时,析构函数没有采用虚函数,生命期结束时导致子类对象占有内存无法释放,造成内存泄漏。
  • 1
  • 2
  • 3

sizeof与strlen对比

sizeof计算的是分配的内存空间实际占用的字节数; strlen计算的是内存空间中字符的个数(不包括"")。
sizeof是运算符,参数可以是指针、数组、类型、对象和函数; strlen是函数,参数必须是字符型指针(char*)。
sizeof是在编译时计算,故参数为数组名时计算的是整个数组的占用内存大小; strlen是在运行时计算,参数为数组名时,数组会退化为指针。
  • 1
  • 2
  • 3

指针与引用的区别

安全性:引用的对象不能改变,安全性好;但指针指向的对象是可以改变的,不能保证安全性。
方便性:引用实际上是封装好的指针解引用(即b->*b),可以直接使用;但指针需要手动解引用,使用更麻烦;
级数:引用只有一级,不能多次引用;但指针的级数没有限制。
初始化:引用必须被初始化为一个已有对象的引用,而指针可以初始化为NULL。
  • 1
  • 2
  • 3
  • 4

指针函数与函数指针

指针函数:返回值是指针的函数,本质上是一个函数;
函数指针:指向一个函数的指针,本质上是一个指针;
  • 1
  • 2

野指针产生与避免

野指针产生的原因:

创建指针时没有对指针进行初始化,导致指针指向一个随机的位置;
释放指针指向的内存后没有置空,从而指向垃圾内存;
在超越变量作用域下使用指针,如:在栈内存被释放之后,指向栈内存的指针会指向垃圾内存;
  • 1
  • 2
  • 3

野指针的避免方法:

在创建指针时必须进行初始化;
使用delete释放指针指向的内存之后必须将指针置空;
  • 1
  • 2

多态:动态多态、静态多态

虚函数实现动态多态的原理、虚函数与纯虚函数的区别

继承时,父类的析构函数是否为虚函数?构造函数能不能为虚函数?为什么?

静态多态:重写、重载、模板

static关键字:修饰局部变量、全局变量、类中成员变量、类中成员函数

const关键字:修饰变量、指针、类对象、类中成员函数

extern关键字:修饰全局变量

volatile关键字:避免编译器指令优化

四种类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast

右值引用

std::move函数

std::forward与std::move的区别

四种智能指针及底层实现:auto_ptr、unique_ptr、shared_ptr、weak_ptr

shared_ptr中的循环引用怎么解决?(weak_ptr)

vector与list比较

vector迭代器失效的情况

map与unordered_map对比

set与unordered_set对比