struct与class的区别
- C语言中struct与class的区别:struct只作为一种复杂数据类型定义的结构体,不能用于面向对象编程;C语言没有class关键字。
- C++语言中struct与class的区别:对于成员访问权限以及继承方式,class默认都是private,struct默认是public;class可以用于表示模板类型,struct不行;一般来说,用到继承时常用class,没用到继承时则使用struct。
内存泄漏与内存溢出的区别
- 内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;例如申请了一个int型的地址空间,但给它存放了long型的数据,就会导致内存溢出。
- 内存泄漏(memory leak):是指程序申请内存后,无法释放已申请的内存空间,内存泄漏多了会导致可用内存空间变小,进一步造成内存溢出。
堆和栈的区别
- 管理方式:堆中资源由程序员控制(通过malloc/free、new/delete,容易产生memory leak),栈资源由编译器自动管理。
- 系统响应:对于堆,系统有一个记录空闲内存地址的链表,当系统收到程序申请时,遍历该链表,寻找第一个大于所申请空间的空间的堆结点,删除空闲结点链表中的该结点,并将该结点空间分配给程序(大多数系统会在这块内存空间首地址记录本次分配的大小,这样delete才能正确释放本内存空间,另外,系统会将多余的部分重新放入空闲链表中)。对于栈,只要栈的剩余空间大于所申请空间,系统就会为程序分配内存,否则报异常出现栈空间溢出错误。
- 空间大小:堆是不连续的内存区域(因为系统是用链表来存储空闲内存地址的,自然不是连续),堆的大小受限于计算机系统中有效的虚拟内存(32位机器上理论上是4G大小),所以堆的空间比较灵活,比较大。栈是一块连续的内存区域,大小是操作系统预定好的,windows下栈大小是2M(也有是1M,在编译时确定,VC中可设置)。
- 碎片问题:对于堆,频繁的new/delete会造成大量内存碎片,降低程序效率。对于栈,它是一个先进后出(first-in-last-out)的结构,进出一一对应,不会产生碎片。
- 生长方向:堆向上,向高地址方向增长;栈向下,向低地址方向增长。
- 分配方式:堆是动态分配(没有静态分配的堆)。栈有静态分配和动态分配,静态分配由编译器完成(如函数局部变量),动态分配由alloca函数分配,但栈的动态分配资源由编译器自动释放,无需程序员实现。
- 分配效率:堆由C/C++函数库提供,机制很复杂,因此堆的效率比栈低很多。栈是机器系统提供的数据结构,计算机在底层对栈提供支持,分配专门的寄存器存放栈地址,提供栈操作专门的指令。
指针与引用的区别
- 指针是一个实体,有分配内存空间,引用只是一个别名,不分配内存空间
- 指针不用但最好初始化,引用必须初始化
- 引用只能初始化一次,指针可以多次赋值
- 可以有const指针,但没有const引用,例如 int* const p合法,int& const p有些编译器会报错,有些编译器会警告并忽视该const修饰符
- 指针可以指向空值,引用不能指向空值
- “sizeof引用”得到的是变量对象的大小,“sizeof指针”得到的是指针本身的大小
- 指针和引用的自增运算符意义不同
- 指针可以有多级,引用只能是一级
五种内存分配区域
- C/C++编译的程序所占用内存区域一般分为以下5个部分:
- 栈区(stack):由编译器自动分配和释放,用来存放函数的参数、局部变量等。其操作方式类似于数据结构中的栈。
- 堆区(heap):一般由程序员分配和释放(通过malloc/free、new/delete),若程序员没有释放,则程序结束时由操作系统回收。它与数据结构中的堆是两回事,分配方式类似于链表。
- 全局/静态区:全局变量和静态变量的存储是放在一块的,初始化的全局变量和初始化的静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由操作系统回收。
- 文字常量区:存放常量值,如常量字符串等,不允许修改,程序结束后由操作系统回收。
- 程序代码区:存放函数体的二进制代码。
- 例子如下:
#include <stdlib.h>
#include <string.h>
int a = 0; // 全局初始化区
char* p1; // 全局未初始化区
int main() {
int a; // 栈区
char s[] = "abc"; // 栈区
char* p2; // 栈区
char* p3 = "123456"; // 123456\0在常量区,p3在栈区
static int c = 0; // 全局/静态初始化区
p1 = (char*) malloc(10);
p2 = (char*) malloc(20); // 分配得来的10和20字节在堆区
strcpy(p1, "123456"); // 123456\0放在常量区,编译器可能将它与p3所指向的"123456"优化成一个地方
return 0;
}
new与malloc的区别
- 属性
- new/delete是操作符,是C++关键字,需要编译器支持;malloc/free是库函数,需要头文件支持。
- 参数
- 使用new操作符动态分配内存时无需指定内存块大小,编译器会根据类型自行计算;malloc分配内存时需要显式地指出所需内存块大小。
- 返回类型
- new操作符内存分配成功时会返回相应对象类型的指针,无需进行强制类型转换,符合类型安全性,分配失败时会抛出bac_alloc异常;malloc分配内存成功时会返回void*类型的指针,需要通过强制类型转换为所需类型,分配失败时返回NULL值。
- 非内部数据对象
- new会先调用operator new函数,申请足够的内存,再调用类型的构造函数,初始化成员变量,最后返回自定义类型的指针;delete会先调用析构函数,然后调用operator delete函数释放内存;malloc/free是库函数,只能动态申请内存及释放内存,无法完成构造函数及析构函数的工作。
- 重载
- C++允许重载new/delete(实际上是重载operator new 和operator delete),特别的,布局new(placement new)就不需要为对象分配内存,而是使用指定一个地址作为内存起始区域,new在这段内存上完成对象的构造函数调用并初始化该内存段,并返回此内存地址;malloc/free不允许重载。
- 内存区域
- new操作符从自由存储区(free stone)上为对象动态分配空间,malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请的,该内存即为自由存储区;堆是操作系统中已分配的对应的内存区域。自由存储区不等于堆,布局new就可以不位于堆中。堆是一个实际的区域,而自由存储区是一个更上层的概念。通常new确实是在堆上申请内存,但是程序员可以自己重载new操作符,使用其他内存来实现自由存储(不常见),另外,C++primer plus这本书上提到的布局new,可以为对象在栈上分配内存。总的来说,自由存储区是new申请的区间的概念。
3种类间关系及区别
Inheritance(继承)
- 表示is-a,如下代码所示:
class A {
private:
int a;
};
class B : public A {
private:
int b;
};
- 继承关系下的构造和析构
==构造由内而外==
Derived的构造函数首先调用Base的default构造函数,然后才执行自己。如,Derived::Derived(...) : ==Base()== { ... };
==析构由外而内==
Derived的析构函数首先执行自己,然后才调用Base的析构函数。如,Derived::~Derived(...) { ... ==~Base()== };
Composition(复合)
- 表示has-a,如下代码所示:
class A {
private:
int a;
};
class B {
private:
A a;
int b;
};
- 复合关系下的构造和析构
==构造由内而外==
B的构造函数首先调用A的default构造函数,然后才执行自己。如,B::B(...) : ==A()== { ... };
==析构由外而内==
B的析构函数首先执行自己,然后才调用A的析构函数。如,B::~B(...) { ... ==~A()== };
Delegation(委托)
- Composition by reference, 如下代码所示:
class A {
private:
int a;
};
class B {
private:
A* a;
int b;
};
原文地址:https://www.cnblogs.com/yiluyisha/p/9188010.html
时间: 2024-11-13 08:50:35