关于C和C++的区别是面试中经常会被问到的问题,本着即将面试的心态,进行知识整理,并对小知识点进行扩展;

C/C++的联系:

C/C++区别:

小知识点补充扩展

是从堆上开辟空间,而new是从自由存储区开辟;(自由存储区是 C++抽象出来的概念,不仅可以是堆,还可以是静态存储区);/free是函数,而new/是关键字;对开辟的空间大小需要严格指定,而new只需要对象名;开辟的空间即可以给单个对象用也可以给数组用,释放的方式都是

free();而new开辟对象数组用的是new[size] ,释放的的时候是 []

(尽管内置类型可能不会引起问题,但是自定义类型的话,[]需要知道有

多少个对象,而这个计数就被放在这块空间的头部);

返回值问题,开辟成功返回void*,需要强转,失败返回NULL,new

成功返回对象指针,失败抛出异常(这就可能会提到C++的机

制),虽然为了最大程度的兼容C,C++的new也支持失败返回NULL,但是一般不

被使用,大家可以了解一下;

是否调用构造和析构,这点应该放在前面,new和free不但负责开辟空间,

还会调用对象的构造函数和析构函数;最好了解一下new的三种表达形式(new运

算符, new(); new();)还有定位new表达式的

使用;

是否可以相互调用,new的实现可以用,的实现不可以使用

new;

是否可以被重载,我们可以重载自己的 new/,但是不可

以重载new///free;

开辟 的内存如果太小,想要换一块大一点的,可以调用实

现,但是new没有直观的方法来改变;

第十点其实前面已经提到,当new中的底层实现如果获取不到更多的内存,

会触发机制,留有一个句柄,看看用户是否设

置了这个句柄,如果设置了就去执行,句柄的目的是看看能不能尝试着从操作系

统释放点内存,找点内存,如果实在不行就抛出异常;而就

没有这种尝试了;——-

扩展_3 常见关键字的作用

**1.static 关键字:**
 修饰全局变量时,会将变量的链接属性变为内部链接属性,并且变量
 的存储位置变为全局静态区;
 修饰 局部变量,改变局部变量的存储位置为静态存储区,改变局部变
 量的生命周期为整个程序开始到结束;
 修饰类的成员变量和函数:属于类而不属于对象,属于所有实例类;
**2.const关键字**
 修饰全局变量:C/C++略有不同,在上文已经提到,即C++的const修
 饰的全局变量可以作为属组的初始化的大小,而C不可以;同时变量的
 值不能被修改;C++利用const的这一属性,代替C中的define进行
 全局常量的定义;扩展_4会就 define,const,inline进行对比
 和分析;
 修饰局部变量:代表局部变量的值不能被修改;
 修饰指针:这个是经常问道的,我举的例子可能不全面,但是是比较
 常见的例子:
 cons t int *p; //修饰的是p所指向的内容不能被改变,p可
 以;
 int const *p; //和上面是一样的;
 int* const p; //修饰的p指针不能改变;
 修饰类的成员变量:必须在初始化列表初始化,除此之外,必须在初
 始化列表初始化的还有,引用类型的数据成员,没有默认构造函数的
 对象成员,如果存在继承关系,如果父类没有默认的构造函数,则也
 必须在初始化列表中被初始化,初始化列表对数据成员的初始化顺序
 是按照数据成员的声明顺序严格执行的;
 修饰类的成员函数:一般放在成员函数的最后面,修饰的是类的成员
 函数中的隐藏参数this指针,代表不可以通过this指针修改类的数据
 成员,声明形式例如:
 Base::void fun() const;
 关于const还有一个问题就是传参和赋值的问题,一般来说,const
 修饰的变量是安全的,没有const修饰的变量是不安全的,一般在传
 参的时候,非const修饰的的变量可以传给const修饰的,而const
 修饰的不可以传给非const修饰的形参,这就相当于把安全的东西交
 给了不安全的人;而赋值的话更不用说了,const修饰的不可以传给
 没有const修饰的变量;
**3.volatile**
 volatile一般修饰变量,而它存在的原因是因为,我们的程序在进行
 编译的时候,编译器会进行一系列的优化,比如,某个变量被修饰为
 const的,编译器就认为,这个值是只读的,就会在寄存器中保存这
 个变量的值,每次需要的时候从寄存器直接读取,但是有时候,我们
 可能会在不经意间修改了这个变量,比如说我们去了这个变量的地
 址,然后强行改变这个变量在内存中的值,那么编译器并不知道,读
 取还是从寄存器中读取,这就造成了结果的不匹配,而volatile声明
 的变量就会告诉编译器,这个变量随时会改变,需要每次都从内从中
 读取,就是不需要优化,从而避免了这个问题,其实,volatile应用
 更多的场景是多线程对共享资源的访问的时候,避免编译器的优化,
 而造成多线程之间的通信不匹配!;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

关键字

首先需要了解什么是隐式转换,即在你没有进行显示的强转的情况

下,赋值运算符左右两个类型不一致的对象进行了类型转换;或者

函数传参的时候进行了类型转换; 而关键字存在的目的就是

禁止类的构造函数进行隐式的类型转换,常见的就是类的对象

就可以隐式类型转换,比如:

 strig s = "hello world";
 因为string 有一个单参的char*构造函数,所有可以用hello w
 orld构造一个string对象,然后调用string 类的拷贝构造函数;
 有时候我们并不希望这种不是我们预期的情况发生,所以,我们可以
 在类的构造函数之前+explicit关键字。禁止隐式转换;
 ---希望读者提建议继续补充!(补充文章中讲到的所有内容的不足之处)
1
2
3
4
5
6
7
8
9

扩展_4 /const/ 对比和分析

作用于程序的预处理阶段,而预处理阶段做的主要工作为下面几个

方面:宏替换,去注释以及条件编译; 起作用的地方就在宏替换阶

段,只是单纯的将宏替换为代码,例如:

#define Add(a+b) a+b
1

下面这段代码用到了这个宏:

int main()
 {
 int a = 1; //如果char a = '1'; 
 int b = 2;
 cout<<Add(a+b);
 /* 替换为cout<<1+2; */
 return 0;
 }
1
2
3
4
5
6
7
8

从上面这个例子我们可以看出的缺点很明显,首先,只 是单纯的代码替换,不会进行类型的检查,再者,我们上面的宏定义 也很粗糙,严格点应该定义为: # Add(a,b) (a)+(b) C++中一般建议使用const,枚举定义常量,这样就会有类型检查; 而宏定义也可以定义出和函数一样的功能: # Swap(type,a,b) {type tmp, tmp = a; a = b; b = tmp;} 其实就算这样写,也还是存在上面提到的问题,并且这样还不能进行调 试,因为宏在预处理阶段就替换了;

于是C++中又提供了一个内联关键字 ,可以实现和相同的

功能,并且支持类型检查和调试,一般声明在函数的定义的前面,不过, 只是对编译器的一种建议,一般如果代码在3-5行左右,且没有复 杂的逻辑结构,例如循环啊,递归啊,就可以声明为,也

是在函数调用的地方替换代码块,所以代码太长的话,容易造成程序膨胀,那么为什么可以支持调试呢?

其实支持调试也只是在dbug模式下,真正起作用是在模

式,正好和相反;

提到,就不得不提友元;被一个类中声明为友元的非本类函数和类,可以访问本类的私有成员,这个关键字的存在感觉有些破坏类的封

装性,而且,友元属性不能被传递和继承;(但是实际中在有些编译器下友元函数被子类继承了,我也很纳闷,读者可以自己验证一下,留言!)

new和malloc的区别_区别对待的另一种说法_区别词

———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,永久会员只需109元,全站资源免费下载 点击查看详情
站 长 微 信: nanadh666

声明:1、本内容转载于网络,版权归原作者所有!2、本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。3、本内容若侵犯到你的版权利益,请联系我们,会尽快给予删除处理!