C++基础知识校招面试题,附答案

目录


       

       

       

1、C++为什么要提出引用?(引用和指针的区别?)

       引用变量在功能上等于一个常量指针(到底是常量指针还是指针常量?有的书上写的常量指针,有的博客里写的指针常量,那就不纠结这个问题吧。总之这里指的是顶层const),即一旦指向某一个单元就不能在指向别处。
(1)我们在用指针的使用经常犯的错误是什么?
       操作野指针;
       不知不觉改变了指针的值,而后还以为该指针正常。
       如果我们要正确的使用指针,我们不得不人为地保证这两个条件。而引用的提出就是解决这个问题。
       引用区别于指针的特性是:
        必须初始化(保证不是野指针);
        一个引用永远指向他初始化的那个对象(保证指针值不变)。
所以引用的提出就是:让人为地保证这两个条件变成让编译器保证。这样可以减少错误的产生。

2程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。

3用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,且通过const的使用,保证了引用传递的安全性。

       

       

       

2、使用const而不是#define来定义常量?

  • const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而后者仅仅进行字符替换,没有类型安全检查,并且在字符替换过程中会产生一些意料不到的错误。
  • const方法可以很方便地用于复合类型。
    如const int a[3]={1,2,3};
  • const标识符遵循变量的作用域原则,可以创建作用域为全局、名称空间、数据块的常量。

       

       

       

3、C++左值和右值的区别?

  • 左值:lvalue(locator value)代表一个在内存中占有确定位置的对象(换句话说就是有一个地址)。
  • 右值:rvalue通过排他性来定义,每个表达式不是lvalue就是rvalue。因此从上面的lvalue的定义,rvalue是在不在内存中占有确定位置的表达式。

       

       

       

4、全局变量?

特点:

  • ① 作用域:全局可见。
           全局变量(外部变量)是在函数外部定义的,它的作用域为从变量的定义处开始,到本程序文件的末尾。
           注:通常把超出一个函数的作用域称为全局作用域,其他几种(如块作用域)不超出一个函数的作用域称为局部作用域。
  • ② 存储空间:静态存储区
           系统会在执行时将全局变量分配在静态存储区,在程序执行期间,对应的存储空间不会释放,一直到程序结束才会释放。
           注:一个程序在内存中占用的存储空间可以分为3个部分:程序区(存放可执行程序的代码)、静态存储区(存放静态变量)、动态存储区(存放动态变量)。
  • ③ 优先度:全局变量优先度低于局部变量
    当全局变量和局部变量重名时,会屏蔽全局变量,局部优先。
           

优点使用全局变量程序运行时速度会快一点,因为内存不需要再分配。
缺点使用全局变量会占用更多的内存,因为其生命期长。

       
全局变量作用域的扩展和限制

  • ① 扩展:使用extern关键字可以对全局变量的作用域进行扩展。
            前面提到,全局变量的作用域为从变量的定义处开始,到本程序文件的末尾。若想在本文件全局变量定义之前引用该全局变量,可以在引用之前用extern关键字对该变量进行说明,有了此说明,就可以从说明之处起,合法地引用该变量。
            若想在一个文件(设为a.cpp)中引用另一个文件(设为b.cpp)中已定义的全局变量,可以在a.cpp中extern关键字对该全局变量进行说明,在编译和连接时,系统就会知道该全局变量已经在其他文件(b.cpp)中定义过了。
           注:在编译时遇到extern,系统会现在本文件中查找全局变量的定义,如果找到,就在本文件中扩展作用域;如果找不到,就在连接时在其他文件中查找全局变量的定义,如果找到,就将作用域扩展到本文件;如果还找不到,按出错处理。

  • ② 限制:使用static关键字可以限制全局变量的作用域。(又称之为隐藏)
           全局变量默认是有外部链接性的,作用域是整个工程,在一个文件内定义的全局变量,在另一个文件中,通过extern对全局变量进行声明,就可以使用全局变量。
           如果希望全局变量仅限本文件引用,而不能被其他文件引用,可以在定义全局变量时在前面加一个static关键字。
           

全局变量和全局静态变量的区别:

       首先,并不是说全局变量在定义时加了static关键字才是静态存储,不加static就是动态存储,不是的。不管加不加static,全局变量都是存储在静态存储区的,都是在编译时分配存储空间的,两者只是作用域不同,全局变量默认具有外部链接性,作用域是整个工程,全局静态变量的作用域仅限本文件,不能在其他文件中引用。

       

       

       

5、static关键字?

特点:用来控制存储方式和可见性

  • ① 存储空间:静态存储区(控制变量的存储方式)
           静态变量存储在静态存储区(存储在静态存储区的变量,如果不显式地对其进行初始化,系统会将其初始化为0),在程序执行期间,对应的存储空间不会释放,一直到程序结束才会释放。
           static控制变量的存储方式体现在局部变量上。局部变量存储在动态存储区,在局部变量定义前加上static,该局部变量就变成了局部静态变量,局部静态变量存储在静态存储区,即使函数调用结束,它占用的存储空间也不会释放,但其他函数不能引用该局部静态变量。当下一次调用该函数时,不会再次对该局部静态变量进行初始化,它的值是上一次函数调用结束时的值。
           对全局变量而言,存储方式没有什么改变,因为全局变量和全局静态变量都存储在静态存储区。
  • ② 作用域:(控制变量、函数的可见性)
           static控制变量的可见性体现在全局静态变量和静态函数上。
           全局变量默认具有外部链接性,作用域是整个工程。使用static关键字可以限制全局变量的作用域,全局静态变量的作用域仅限本文件,它对在其他文件不可见,也就是说不能在其他文件中引用该全局静态变量,但其他文件中可以定义和它名字相同的变量,不会发生冲突。
           在函数的返回类型前加上static关键字,函数即被定义为静态函数。静态函数与普通函数的不同在于,它只能在声明它的文件当中可见,不能被其它文件使用,其它文件中可以定义相同名字的函数,不会发生冲突。
           局部静态变量的作用域与局部变量的作用域相同,其作用域都是从定义开始到函数或程序块结束为止。

       
类中的static关键字:

       在类中声明static变量或者函数时,初始化时使用作用域运算符(::)来标明它所属类,静态成员是类的成员(所有对象中共享的成员),而不是某一个对象的成员。

  • ① 静态数据成员
           在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员。
           静态数据成员和普通数据成员一样遵从public,protected,private访问规则。
    对于非静态数据成员,每个对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类的所有对象共享访问。也就是说,静态数据成员是该类的所有对象所共有的。对该类的多个对象来说,静态数据成员只会被分配一次内存,供所有对象共用。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新。
           因为静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定的对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它。
           同全局变量相比,使用静态数据成员有两个优势:
           静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性;
           可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能;

  • ② 静态成员函数
           与静态数据成员一样,我们也可以创建一个静态成员函数,它为类的全部服务而不是为某一个类的具体对象服务。静态成员函数与静态数据成员一样,都是类的内部实现,属于类定义的一部分。普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this是缺省的,如函数fun()实际上是this->fun()。但是与普通函数相比,静态成员函数由于不与任何的对象相联系,因此它不具有this指针。
           非静态成员函数可以任意地访问静态成员函数和静态数据成员;
           静态成员函数不能访问非静态成员函数和非静态数据成员;静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
           

什么时候用static?

       需要一个数据对象为整个类而非某个对象服务,同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部,对外不可见。

为什么要引入static?

       函数内部定义的变量,在程序执行到它的定义处时,编译器为它在栈上分配空间,大家知道,函数在栈上分配的空间在此函数执行结束时会释放掉,这样就产生了一个问题:如果想将函数中此变量的值保存至下一次调用时,如何实现?最容易想到的方法是定义一个全局的变量,但定义为一个全局变量有许多缺点,最明显的缺点是破坏了此变量的访问范围(使得在此函数中定义的变量,不仅仅受此函数控制)。

       

       

       

6、C++和C的区别?

设计思想上:
C++是面向对象的语言,而C是面向过程的结构化编程语言,C++在C的基础上增加了类。

语法上:
C++具有封装、继承和多态三种特性。
C++相比C,增加了许多类型安全的功能,比如强制类型转换。
C++支持范式编程,比如模板类、函数模板等。
在C++中,引用是一个经常使用的概念。引用型变量是其他变量的一个别名,我们可以认为他们只是名字不相同,其他都是相同的。
在C++语言中,仍然支持malloc()和free()来分配和释放内存,同时增加了new和delete来管理内存。
C++支持函数重载,允许有相同的函数名,不过它们的参数类型不能完全相同,这样这些函数就可以相互区别开来。而这在C语言中是不允许的。
       

       

       

7、智能指针(smart pointer)?

       智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。
       C++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr,其中后三个是c++11支持,并且第一个已经被11弃用。
       
为什么要使用智能指针?
       动态内存的使用中很容易出现问题。比如,申请的空间忘记释放,造成内存泄漏;或者在后面还会使用到该指针的情况下释放了内存,在这种情况下就引用了非法内存的指针。
       用智能指针可以很大程度上的避免这些问题,因为智能指针就是一个类(而且还是像vector这样的模板类,当我们创建一个智能指针时,还必须提供额外的信息——指针可以指向的类型),当超出了类的作用域是,类会自动调用析构函数,析构函数会自动释放资源。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间。
       
shared_ptr:
       shared_ptr允许多个指针指向同一个对象。当指向某一个对象的最后一个shared_ptr被销毁时,shared_ptr类会自动销毁此对象,它是通过析构函数来完成销毁工作的。
       
weak_ptr:
       weak_ptr被设计为与shared_ptr共同工作,可以从一个shared_ptr或者另一个weak_ptr对象构造而来。weak_ptr是为了配合shared_ptr而引入的一种智能指针,它更像是shared_ptr的一个助手而不是智能指针,因为它不具有普通指针的行为,没有重载 operator* 和 operator-> ,因此取名为 weak,表明其是功能较弱的智能

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值