2018秋招面试问题(二、C++基础问题)

目录

c语言的代码段、数据段、bss段

C++中为什么空类的大小为1?为什么成员函数不占大小?为什么有了成员变量之后就不用加1了?

如何理解面向对象(oop)

面向过程编程、OOP面向对象编程和泛型编程

typedef的作用

关于typedef的注意点

断言assert了解吗?

静态局部变量、静态全局变量、普通全局变量之间的区别

fopen文本模式和二进制模式的区别

对C++顶层const和底层const的区别

C++11有没有了解过?

智能指针

shared_ptr的计数机制

C++的内存分配\内存管理方式

C的内存管理方式

自由存储区和堆是两块不同的内存区域吗?它们有可能相同吗?


c语言的代码段、数据段、bss段

编译器在编译程序的时候,将程序中的所有的元素分成了一些组成部分,各部分构成一个段,所以说段是可执行程序的组成部分。

代码段:代码段就是程序的可执行部分,直观理解就是函数堆叠组成的。

数据段:数据段存放一些程序中的数据,初始化了的全局变量、静态变量都放在数据段。

bss段未初始化的全局变量和静态变量都放在bss段。

C++中为什么空类的大小为1?为什么成员函数不占大小?为什么有了成员变量之后就不用加1了?

  1. 被编译器插进去的一个char ,使得这个class的不同实体(object)在内存中配置独一无二的地址。 空类在实例化后会在内存得到了独一无二的地址。
  2. 类中的静态成员变量也是不占类空间的,因为静态属于对象共享的,不为每个对象独有。所以能计入对象大小(类空间的)都是对象所独有的。类的所有对象都共用内存中同一份成员函数。每个对象通过把this指针以及其他参数传递方式来调用成员函数。
  3. 在有成员变量之后,对象实例化就可以通过不同成员来得到不同的内存地址,就不需要那个标识地址不同的char了。

如何理解面向对象(oop)

面向对象有三大特性,封装、继承和多态。

封装就是将一类事物的属性和行为抽象成一个类,使其属性私有化,行为公开化,提高了数据的隐秘性的同时,使代码模块化。这样做使得代码的复用性更高。

继承就是一个类继承另一个类,实现了代码的复用,继承后子类自动拥有了父类的属性和方法,子类也可以写自己特有的属性和方法,目的是实现功能的扩展。

多态就是调用相同的方法,参数也相同时,但表现的行为却不同,这是由虚函数来实现的。

面向过程编程、OOP面向对象编程和泛型编程

面向过程是一种以过程为中心的编程思想,考虑的是实际的实现过程,比如说c语言,以函数作为基本单元,就是通过函数来体现的。OOP是面向对象编程,把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数,通过封装、继承、多态来实现程序。

C++中还包括重载、多态、继承、输入输出流这些。

泛型编程就是提供了模板,将类型参数化,用template <typename T>,比如STL容器,都属于泛型编程,其中的类型可变。

typedef的作用

第一,定义别名。可以定义一种类型的别名,也可以替复杂声明定义一个别名。可以用来同时声明多个指针。比如char* a,b;只是定义了一个指针和一个变量。如果有typedef char* PCHAR;就可以连续定义多个指针,PCHAR a,b,c,d; 和char*a,*b是等价的。typedef更直观。

第二,在结构体中用来省略struct

typedef struct ListNode

{

struct ListNode *next;

int val;

}ListNode;

比如链表的结构体,ListNode就代替struct ListNode

第三,可以用来定义与平台有关的数据类型。当跨平台的时候,只需要修改typedef就行了。

关于typedef的注意点

  • typedef是定义了一种类型的新别名,不同于宏,不是简单的字符串替换。比如:

typedef char* PSTR;

const PTSR p = “abc”;//这个地方const限制了p只读

p++;//错误×

记住const和 typedef一起出现时,绝不是简单的字符替换

  • typedef是一个存储类型的关键字(同auto、extern、mutable、static、register等一样),虽然它实际上不影响对象的存储特性。所以要注意不能和别的存储类型同时使用。

typedef static int INT;//会报错

断言assert了解吗?

assert是一个,相当于一个if语句,在debug模式下使用的,assert中的表达式为真,程序正常运行,表达式为假,就会终止程序。频繁地调用assert会影响程序的性能。禁用assert,就是在include后面加#define NDEBUG。

#include
#define NDEBUG
#include

静态局部变量、静态全局变量、普通全局变量之间的区别

首先它们都存在内存的全局存储区。

一个程序由多个源文件组成。这三种变量的生命期都是整个程序。

静态局部变量的作用域是定义它的那个函数内部,且只能初始化一次。

静态全局变量的作用域是整个源文件,不可extern到别的源文件中使用。

普通全局变量的作用域是整个源文件,但是可以extern到别的源文件中使用。

fopen文本模式和二进制模式的区别

FILE * fopen(const char * path,const char * mode);

首先文本文件是基于字符编码的文件,如ASCII码、Unicode等,包括xml文件、html超文本文件、c源程序文件等。二进制文件是基于值编码的文件,如word文件、图像格式文件JPG等。

fopen中二进制模式是原封不动的读写文件的全部内容。

文本模式下,你写进去、读出来的,和实际存储的数据,两者不一定相同;

二进制模式下,你写进去、读出来的,和实际存储的数据,两者一定相同。

以文本方式打开文件的话,当读取文件的时候,系统会将所有的"/r/n"(回车换行)转换成"/n"(换行);当写入文件的时候,系统会将"/n"转换成"/r/n"写入。

r 打开只读文件,该文件必须存在。

r+ 打开可读写的文件,该文件必须存在。

rb+ 读写打开一个二进制文件,只允许读写数据。

rt+ 读写打开一个文本文件,允许读和写。

w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件

w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。

wb 只写打开或新建一个二进制文件;只允许写数据。

wb+ 读写打开或建立一个二进制文件,允许读和写。

wt+ 读写打开或着建立一个文本文件;允许读写。

有 + 表示允许读写。

wb+和rb+都可以进行读写,区别在于wb+可以打开或者建立一个文件。

对C++顶层const和底层const的区别

对于普通变量没有顶层底层的区别,对于指针来说才有区别。

顶层const指的是常量指针,也就是指针本身不可改变。*const

底层const指的是指向常量的指针,也就是指针指向的值不可改变。const* 就是底层。

C++11有没有了解过?

C++11C++编程语言的一个标准,之前的标准有C++98以及C++03。相比于C++03,C++11标准包含核心语言的新机能,而且扩展C++标准程序库。

例如:

for循环使用更简单

 

引入了空指针nullptr解决NULL二义性

void foo(int n);

void foo(char* cArr);

上面声明了两个重载函数,当我调用foo(NULL),编译器将会调用foo(int)函数,而实际上我是想调用foo(char*)函数的。为了避免这个歧义,C++11重新定义了一个新关键字nullptr,充当单独空指针常量。

引入了 auto 和 decltype 这两个关键字实现了类型推导,auto推导变量,decltype推导表达式。

auto会忽略掉顶层const,保留底层const。

const int i = 5;

auto a = i; //a是int类型而不是const int

const auto a = i;//a就是才是const int型

引入了智能指针

智能指针

智能指针是对普通指针增加了一层封装机制,用来方便地管理一个对象的生命周期(及对象什么时候被删除或被析构由智能指针本身决定,不需要用户管理)

智能指针的作用:智能指针是为了避免内存泄露的问题,替代了new和delete。

关键字auto_ptr、unique_ptr、shared_ptr和weak_ptr,头文件是<memory>。其中auto_ptr是c++98中的,c++11将其抛弃,是为了避免潜在的内存崩溃的问题(当两个指针指向同一个内存的时候,会释放两次),替换为unique_ptr、shared_ptr则不会崩溃。unique_ptr会在编译时就报错,而shared_ptr则会计算引用的次数,就不会出现多次删除。

auto_ptr<int> m (new int(5));

如果shared_ptr的两个指针b赋值给a,则两个指针的计数值都会增加。shared_ptr指针的计数值指的是指向这块内存的指针个数。

shared_ptr的计数机制

构造函数中计数初始化为1;

拷贝构造函数中计数值加1;

赋值运算符中左边的引用对象计数-1,右边的引用对象技术+1;

析构函数中引用计数-1,当减为0,就会自动delete释放掉对象空间。

C++的内存分配\内存管理方式

C++中,内存区分为五个区,分别是堆、栈、全局存储区、常量存储区、自由存储区。

常量存储区:常量字符串等;

全局存储区:全局变量、静态变量,程序结束后由系统释放。

栈区:局部变量、函数的参数变量,由编译器自动分配释放(栈地址是向下增长的)。

堆区:由程序员分配释放,malloc在堆上分配的内存块,使用free释放内存。

自由存储区:是通过new和delete动态分配和释放对象的抽象概念,new所申请的内存区域在c++中称为自由存储区。

C的内存管理方式

堆、栈、全局区、常量区。

自由存储区和堆是两块不同的内存区域吗?它们有可能相同吗?

自由存储区和堆是两个不同的概念,它们有可能指向同一块内存区域。

基本上,所有的C++编译器默认使用堆来实现自由存储,也就是new和delete也许会按照malloc和free的方式来被实现,这时藉由new运算符分配的对象,说它在堆上也对,说它在自由存储区上也正确,这时候他们就是相同的内存。而如果程序员也可以通过重载操作符,改用其他内存来实现自由存储,例如全局变量做的对象池,这时自由存储区就区别于堆了,这时候就是不同的内存区域。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值