基础介绍
C语言面向过程,重点在于算法和数据结构。C程序的设计首先考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程(事务)控制)。
C++语言是面向对象语言,首先考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事务)控制。
它在C的基础上添加了面向对象、模板等现在程序设计语言的特性。拓展了面向对象设计的内容,如类、继承、虚函数、模板和容器类等等,使之更加符合现代程序设计的需要。
C++是C语言的继承,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计(泛型编程),还可以进行以继承和多态为特点的面向对象的程序设计(面向对象编程),支持类、封装、继承、多态等特性。
面向对象编程:面向对象是一种对现实世界理解和抽象的方法、思想,通过将需求要素转化为对象进行问题处理的一种思想。
类:类定义了事物的属性和它可以做到的(它的行为)。一个类的方法和属性被称为“成员”。类是在对象之上的抽象,对象则是类的具体化,是类的实例。
封装性:封装使数据和加工该数据的方法(函数)封装为一个整体,把对象的设计者和对象的使用者分开,使用者不必知晓行为实现的细节,可以增加安全性。
继承性:继承性是子类共享父类之间数据和方法的机制。一个类直接继承其它类的全部描述,同时可修改和扩充。可以增强代码的复用性。
多态性:对象根据所接收的消息而做出动作。同一消息为不同的对象接收时可产生完全不同的行动,这种现象称为多态性。使具有不同内部结构的对象共享相同的外部接口。可以增加扩展性。
面向对象与面向过程的区别?
面向过程是一种以过程为中心的编程思想,以算法进行驱动;面向对象是一种以对象为中心的编程思想,以消息进行驱动。
面向过程编程语言的组成:程序=算法+数据;面向对象编程语言的组成:程序=对象+消息。
以洗衣服为例:
- 面向过程:放衣服(方法)-->加洗衣粉(方法)--> 加水(方法)--> 漂洗(方法)--> 清洗(方法)--> 甩干(方法)
- 面向对象:new 出两个对象 ”人“ 和 ”洗衣机“
”人“ 加入属性和方法:放衣服(方法)、加洗衣粉(方法)、加水(方法)
”洗衣机“ 加入属性和方法:漂洗(方法)、清洗(方法)、甩干(方法)
然后执行:
人.放衣服(方法)-> 人.加洗衣粉(方法)-> 人.加水(方法)-> 洗衣机.漂洗(方法)-> 洗衣机.清洗(方法)-> 洗衣机.甩干(方法)
面向对象的特征是什么?
面对对象的3个要素:封装,继承,多态。面向对象中所有对象都可以归属为一个类。
- 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏
- 继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
- 多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
如何实现多态
有一对继承关系的两个类,这两个类里面都有一个函数且名字、参数、返回值均相同,然后我们通过调用函数来实现不同类对象完成不同的事件。
实现多态,有二种方式,覆盖,重载。
区别:重载实现于一个类中;重写实现于子类中。
重载(Overload):是一个类中多态性的一种表现,指同一个类中不同的函数使用相同的函数名,但是函数的参数个数或类型不同。可以有不同的返回类型;可以有不同的访问修饰符;可以抛出不同的异常。调用的时候根据函数的参数来区别不同的函数。(函数名相同,其他可以不同)
重写(Override):是父类与子类之间的多态性,是子类对父类函数的重新实现。函数名和参数与父类一样,子类与父类函数体内容不一样。子类返回的类型必须与父类保持一致;子类方法访问修饰符的限制一定要大于父类方法的访问修饰(public>protected>default>private);子类重写方法一定不能抛出新的检查异常或者比被父类方法申明更加宽泛的检查型异常。(只有函数内容可以不同,访问修饰要更大)
全局变量是好是坏?
优点:
- 全局可见:任何一个函数或线程都可以读写全局变量,使得变量同步变得简单。
- 内存地址固定:全局变量的内存地址是固定的,读写效率较高。
- 生命周期长:全局变量自程序开始时创建,直到所有函数运行结束后才被释放。
- 减少变量个数:可以减少变量的个数,减少由于实际参数和形式参数的数据传递带来的时间消耗。
缺点:
- 长期占用内存:全局变量存放在静态存储区,系统需要为其分配内存,直到程序结束才会释放。
- 影响函数封装性:使用全局变量会破坏函数的封装性,降低函数的重入性。
- 降低代码可读性:全局变量可能会出现在程序中的各个环节,调试和维护会变得困难。
- 降低函数移植性:依赖全局变量的函数在移植时可能会遇到问题。
- 读写延迟:全局变量的读写可能会出现延迟,尤其是在写操作时
浅拷贝和深拷贝
浅拷贝(Shallow Copy)是指创建一个新对象,并将原对象的字段值复制到新对象中。
- 字段是基本类型(如
int、double等),则直接复制值
- 字段是引用类型(如对象、数组等),则复制引用(即内存地址),而不是复制引用指向的对象本身。如果修改新对象中的引用类型字段,原对象中的对应字段也会被修改。
深拷贝(Deep Copy)是指创建一个新对象,并递归地复制原对象的所有字段。如果字段是引用类型,则创建该字段的新副本,而不是复制引用。深拷贝后,新对象和原对象完全独立,修改一个对象不会影响另一个对象。
【java】【c++】java和c++和c的区别(准备下英文)
- Java不能在类之外的地方定义全局变量,只能在一个类中定义静态变量来实现一个全局变量。 C/C++可以直接在类之外定义全局变量。 Java can't define global variables outside a class, it can only define static variables in a class as a global variable.
- Java不支持C/C++的goto语句,而是通过try、catch来代替C/C++的goto来处理异常时控制。 Java doesn't support "goto" statements of C/C++, but uses try/catch syntax instead of "goto" for exception control.
- C/C++可以通过指针进行内存地址操作,例如通过指针对某内存地址进行显式类型转换,而这种操作访问私有成员破坏了安全性。 Java对指针进行完全的控制,不能在程序中进行任何指针操作,Java中的数组作为类实现,解决了关于数组的很多C/C++难以检查的错误。 C/C++ can operate memory address through pointer. For Example, C/C++ makes explicitly conversion to a memory address by pointer, which destroys the security of the program because it accesses private members. Java Controls pointer completely, and can not operate any pointer in the program. The array in Java is implemented as a class, which solves many errors about array which are difficult to check in c/c++.
- 在C语言中通过malloc和free函数分配和释放内存;C++中可以通过new和delete进行内存的分配和释放。在Java中通过new运算符分配内存,进行对象实例化,而分配内存时随着程序运行动态分配,且Java能够进行自动管理和自动垃圾回收,防止内存资源产生的操作错误和浪费。 In C language, malloc function and free function are used to allocate and release memory; In C + +, memory can be allocated and released by new and delete keywords. In Java, the new operator is used to allocate memory and instantiate objects, and the allocated memory is dynamically allocated with the running of the program. Java can automatically manage memory and recycle garbage, so as to prevent memory operation errors and memory waste.
- C/C++对于不同的平台,数据类型的长度不同,代码不可移植。Java对数据类型总是分配固定长度位数,保证平台无关性。 The length of data type of C/C++ is different in different platforms, so the code is not portable. Java always allocates a fixed number of bits to data type to ensure platform independence.
- C++可以通过指针进行任意类型的转换,Java在进行类型转换时会进行类型相容性检查,防止不安全的转换。 C++ can do any type conversion by pointer. Java will check the type compatibility to prevent unsafe conversion.
- C/C++中用头文件声明类的原型及全局变量、库函数,在大的系统中难以维护这些文件。Java不支持头文件,所有类成员的类型和访问权限都封装在一个类中,运行时系统对访问会进行控制防止对私有成员的操作;导入其他类要使用import语句。 In C/C++, header files are used to declare class prototypes, global variables and library functions, which are diffcult to maintain in large systems. Java does not support header files. The types and access rights of all class members are encapsulated in one class. When the program is running, the system will control the access to prevent the operation of private members.
- C++中的结构体和联合体所有成员都是共有的,这有一定的安全问题。Java中没有结构体和联合体,一切内容都封装在类中。 All members of C++ structure and union are public, so there are some security problems. There is no structure or union in Java, everything is encapsulated in class.
- C++支持宏定义,Java不支持宏定义,而是通过final来声明一个常量,实现宏定义中常量的定义。 C + + supports macro definition. Java does not support macro definition, but declares a constant through the final keyword to realize the definition of constant equivalent to macro definition.
【c++】指针和变量的自增自减有什么不同?
变量的自增自减是改变变量的值,指针的自增自减是改变指针的指向地址。
【c++】宏定义与操作符的区别?
宏定义是C++的预处理命令之一,它是一个替换操作,不做计算和表达式求解,不占内存和编译时间。
例:
#define PI 3.14【c++】虚函数与纯虚函数的特点?
虚函数必须是基类的非静态成员函数,使用
virtual 声明,允许派生类对其进行重写(override),实现运行时多态。纯虚函数是虚函数的一个子集,含有纯虚函数的类就是抽象类,它不能生成对象。
【c++】C++ 中 new 与 malloc 的不同
new从自由存储区申请空间,malloc从堆上申请空间
new的返回类型安全,malloc需要强制类型转换
- 内存分配失败时,
new抛出bad_alloc异常,malloc返回NULL
new可以根据类型自动计算所需内存大小,malloc需要指定内存空间大小
new会自动调用构造函数,malloc不会
- C++ 提供
new[]专门处理数组,malloc无类似机制
operator new可以被重载,malloc无类似机制
- 当内存分配不足时,
operator new会调用用户指定的错误处理函数(new_handler),malloc无类似机制
【c++】如何使用纯虚函数?
纯虚函数用来定义没有意义的实现,用于抽象类中需要交给派生类具体实现的方法。
主要作用是定义接口规范,强制要求派生类必须实现这些函数,从而实现接口的统一和标准化。
【c++】引用与值传递的区别?
值传递传递的是一个值的副本,函数对形参的操作不会影响实参的值;
引用传递传递的是引用对象的内存地址,函数对形参的操作会影响实参的值,实参的值会随着形参的值的改变而改变。
【c++】指针(*)、取地址(&)、解引用(*)与引用(&)
指针是一个包含了另一个变量地址的变量。
例:
int *p = # //将变量num的地址取出来(&), 存到指针p中① 定义一个指针
int *p; ② 将一个指针解引用得到该地址所存的值
cout << *p; ③ 取地址,将某个变量在内存中所存放的地址拿到
cout << #④ 引用,可以理解为给变量起别名,作用在引用上的所有操作事实上都是作用在该引用所绑定的对象上。
int val = 7; int &refval = val;【c++】指针与引用的区别?
- 指针是一个变量,存储的是地址,指向内存的一个存储单元;引用和原来的变量本质上是同一个东西,只是原变量的一个别名。
- 引用在定义时被初始化一次,之后不可变,指针的值在初始化后可变;
- 指针的值可以为空,引用不能为空,且引用在定义时必须初始化;
- 指针和引用的自增(++)运算意义不一样。程序为指针变量分配内存区域,而引用不需要分配内存区域,所以指针自增操作是指针变量的自增,引用自增操作是变量值的自增。
sizeof引用得到的是所指向的变量(对象)的大小,而sizeof指针得到的是指针本身的大小;
【c++】类与结构体有什么区别?
- 默认访问级别不同;结构体的成员和成员函数在默认情况下的访问级别是公有的(public),类的成员和成员函数在默认情况下的访问级别是私有的(private)
- 结构体存储在栈中,类的实例化可以存储在栈中,也可以存储在堆中;
- 结构体的执行效率比类要高
- 结构体没有析构函数,类有析构函数
- 结构体不可以继承,类可以继承
【c++】覆盖与隐藏概述?
覆盖override:覆盖指的是在子类和父类中,存在函数名、参数均相同的函数,并且父类的该函数为虚函数。
隐藏hide:隐藏指的是在子类与父类中,存在函数名相同、参数不同的函数,此时无论父类函数是否为虚函数,父类函数都会被被隐藏,或者存在函数名、参数均相同的函数,此时只有当父类函数不为虚函数时,父类函数才会被隐藏。
【c++】支持参数个数不确定的函数吗?
支持。
【c++】什么是内联函数?
内联函数(Inline Function) 是 C++ 中的一种函数优化机制,通过在编译时将函数体直接插入调用处来减少函数调用的开销。它的主要目的是提高程序的运行效率,尤其是在频繁调用小型函数时。
【c++】什么是静态函数?如何使用静态函数?
静态函数是用static修饰符修饰的函数,在c++中分为静态成员函数和静态全局函数。
静态成员函数是类的成员函数,但它属于类本身,而不是类的某个实例。因此,它可以通过类名直接调用,而不需要创建类的对象。
特点
- 属于类,而非对象:静态成员函数没有
this指针,因为它不与任何特定的对象关联。
- 只能访问静态成员:静态成员函数只能访问类的静态成员变量和静态成员函数,不能访问非静态成员。
- 无需实例化:可以直接通过类名调用。
类中如果函数调用的结果不会访问或者修改任何对象数据成员,这样的成员声明为静态成员函数比较好。
静态全局变量是用static修饰符修饰的全局函数,作用于被限制在当前文件中,其他文件无法访问该函数。
【c++】函数重载及作用域?
函数重载是指在相同作用域下,具有相同名称而不同参数列表的多个函数。
【c++】什么是泛型编程?
泛型编程就是以独立于特定类实现的方式编写代码,针对不同的类型提供通用的实现。
【c++】如何实现泛型编程?
C++中泛型编程的实现是使用C++中的模板技术来实现的,主要是设计函数模板和类模板。
【c++】什么是函数模板?(Function Template)
函数模板是C++中的一种技术,它允许我们使用模板来定义参数化类型的非成员函数。通过函数模板,我们可以编写一个通用的函数,这个函数可以接受不同类型的参数,并且在编译时根据传递的参数类型自动生成相应的函数实例。这样,程序可以使用不同的参数类型调用相同的函数,而不需要为每种类型单独编写一个函数。
【c++】什么是类模板?
类模板是使用模板技术的类,描述了能够管理其他数据类型的通用数据类型。类模板技术通常用于建立包含其他类型的容器类(队列、链表、堆栈等)。
【c++】程序的编译执行过程
第一步,预处理。这一步处理 头文件、条件编译指令和宏定义。
第二步,编译。将第一步产生的文件连同其他源文件一起编译成汇编代码。
第三步,汇编。将第二步产生的汇编源码转换为 object file.
第四步,链接。将第三步产生的一些object file 链接成一个可执行的文件。
【c++】【java】多态在 Java 和 C++ 中实现的不同
【c++】【java】解释对编译
Java是一种解释性(或者说半解释半编译)语言,意味着其在执行时会被“翻译”为二进制形式,也就是java跑得时候必须有人(jvm)去解释它(现在的Java语言,其执行方式已经不仅仅是解释执行方式了,即时编译器(JITC、just-in-time compiler)技术和原型编译技术的出现大大提高了JAVA的运行效率)。
而C++则是编译语言,意味着程序只能在特定操作系统上编译并在特定系统上运行,也就是说C++一步到位成机器语言的。
【java】内存安全
Java是一种内存安全型语言,主要通过以下机制来保证内存安全:
- 自动内存管理(垃圾回收机制),Java 使用垃圾回收器(Garbage Collector, GC)自动管理内存分配和释放。程序员不需要手动分配或释放内存,垃圾回收器会自动回收不再使用的对象。这避免了常见的内存泄漏和悬空指针问题。
- 边界检查,Java 在访问数组或集合时会对索引进行边界检查,如果越界会抛出
ArrayIndexOutOfBoundsException异常,而c++越界访问可能会导致缓冲区溢出或程序崩溃
- 没有指针,只有引用,引用由 JVM 管理,避免了野指针和指针算术错误。
- Java 是强类型语言,所有类型转换都在编译时或运行时进行严格检查。
【java】多重继承
Java不支持多重继承,但允许一个类实现多个接口
多重继承,允许多个父类派生一个子类。也就是说,一个类允许继承多个父类。
【java】【c++】数据结构
Java 是完全面向对象的语言,所有方法和数据都必须是类的一部分。除了基本数据类型之外,其余类型的数据都作为对象型数据。例如,对象型数据包括字符串和数组。类将数据和方法结合起来,把它们封装在其中,这样每个对象都可实现具有自己特点的行为。
而 C++将函数和变量定义为全局的,然后再来调用这些函数和变量,从而增加了程序的负担。此外,Java 还取消了 C/C++中的结构和联合,使编译程序更加简洁
【java】【c++】操作符重载
Java 不支持操作符重载,操作符重载被认为是 C++的突出特征。
【c++】【java】预处理功能
C/C++在编译过程中都有一个预编译阶段,即预处理器。预处理器为开发人员提供了方便,但增加了编译的复杂性。
Java 允许预处理,但不支持预处理器功能,因为 Java 没有预处理器,所以为了实现预处理,它提供了引入语句(import),但它与 C++预处理器的功能类似。
【c++】【java】【c】缺省参数函数
Java和c语言不支持缺省参数函数,而 C++支持。
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。
- 半缺省参数必须从右往左依次且连续来给出
- 缺省参数不能在函数声明和定义中同时出现
【c++】【java】字符串
C 和 C++不支持字符串变量,在 C 和 C++程序中使用“Null”终止符代表字符串的结束。
在 Java 中字符串是用类对象(String 和 StringBuffer)来实现的,在整个系统中建立字符串和访问字符串元素的方法是一致的。Java 字符串类是作为 Java 语言的一部分定义的,而不是作为外加的延伸部分。此外,Java还可以对字符串用“+”进行连接操作。
【c++】【java】goto语句
c和c++中的goto语句也称为无条件转移语句,通常与条件语句配合使用,用来实现条件转移, 构成循环,跳出循环体等功能。
但是,在结构化程序设计中一般不主张使用goto语句, 以免造成程序流程的混乱,使程序的可读性变差,增加程序调试的难度。
Java 不提供 goto 语句,虽然Java指定 goto 作为关键字,但不支持它的使用,这使程序更简洁易读。
【c++】【java】类型转换
C++中支持自动强制类型转换,例如可将一个浮点值赋予整型变量,并去掉其尾数。
Java不支持自动强制类型转换,需要时需要由程序显式进行强制类型转换。
【c++】【java】应用场景
java侧重于大型企业级应用开发,C++侧重于底层应用开发。
【java】JVM的垃圾回收算法
- 标记-清除(Mark-and-Sweep)算法
- 效率问题:标记和清除两个过程效率都不高。
- 空间问题:标记清除后会产生大量不连续的内存碎片。
分为“标记(Mark)”和“清除(Sweep)”阶段:首先标记出所有不需要回收的对象,在标记完成后统一回收掉所有没有被标记的对象。

- 复制算法(Copying)
将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。

- 标记-整理(Mark-and-Compact)算法
标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。

- 分代收集算法
当前虚拟机所使用的垃圾回收算法,核心思想是根据对象存活的不同生命周期将内存划分为不同的域,一般分为老生代(Tenured/Old Generation)和新生代(Young Generation)。
老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃圾回收时都有大量垃圾需要被回收。
新生代采取Copying算法,老生代采用Mark-Compact算法。
一般将新生代划分为一块较大的Eden空间和两个较小的Survivor空间(From Space, To Space),每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将该两块空间中还存活的对象复制到另一块Survivor空间中。

【c++】【python】异同点?
【c++】【java】内存管理有什么不同,两种语言定义的变量在内存中相同吗?


如果创建一个对象,对象存放在堆中,而栈中存放了指向其的地址。如果是基本变量就直接存放在栈中。
栈和堆的区别
- 栈由系统自动分配,而堆是人为申请开辟
- 栈获得的空间较小,而堆获得的空间较大
- 栈由系统自动分配,速度较快,而堆一般速度比较慢
- 栈是连续的空间,而堆是不连续的空间
循环引用怎么解决?
循环引用指两个对象相互强引用了对方,从而导致两个对象都无法被释放,引发了内存泄漏现象,互相引用变量的引用计数都为1,本质上是引用计数的原因。
解决办法:只靠强引用计数方式,会存在循环引用的问题,导致对象永远无法被释放,弱引用(weak reference)就是专门用来解决循环引用问题的:
「若 A 强引用了 B,那 B 引用 A 时就需使用弱引用,当判断是否为无用对象时仅考虑强引用计数是否为 0,不关心弱引用计数的数量」
这样就解决了循环引用导致对象无法释放的问题,但这会引发野指针问题:当 B 要通过弱指针访问 A 时,A 可能已经被销毁了,那指向 A 的这个弱指针就变成野指针了。在这种情况下,就表示 A 确实已经不存在了,需要进行重新创建等其他操作。
【python】list和dict的区别
dict
查找和插入的速度极快,不会随着key的增加而变慢;
需要占用大量的内存,内存浪费多。
因此,dict是用空间来换取时间。
list
查找和插入的时间随着元素的增加而增加;
占用空间小,浪费内存很少。
c++和c的区别
1) C 是面向过程的语言,而 C++是面向对象的语言。
2) C和C++动态管理内存的方法不一样,C是使用malloc/free函数,而C++除此之外还有 new/delete 关键字。
3) 接下来就不得不谈到 C 中的 struct 和 C++的类,C++的类是 C 所没有的,但是 C 中的struct是可以在C++中正常使用的,并且C++对struct进行了进一步的扩展,使struct 在 C++中可以和 class 一样当做类使用,而唯一和 class 不同的地方在于 struct的成员默认访问修饰符是public,而class默认的是private。
4) C++支持函数重载,而C不支持函数重载,而C++支持重载的依仗就在于C++的名字修饰与C不同,例如在C++中函数int fun(int ,int)经过名字修饰之后变为 _fun_int_int ,而C是 _fun,一般是这样的,所以C++才会支持不同的参数调用不同的函数。
5) C++中有引用,而C没有。
6) 当然还有C++全部变量的默认链接属性是外链接,而C是内链接。
7) C 中用const修饰的变量不可以用在定义数组时的大小,但是C++用const修饰的变量可以(如果不进行&,解引用*的操作的话,是存放在符号表的,不开辟内存);
8) 当然还有局部变量的声明规则不同,多态,C++特有输入输出流之类等等。






