面试问题集锦--2

1. extern关键字

Extern放在变量或者函数前,---- > 标示变量或者函数的定义在其他文件中

作用:

  1. 当它与“C”一起连用的时候,如:extern "C" void fun(int a,int b);则告诉编译器在编译fun这个函数时候按着C的规矩去翻译,而不是C++的(这与C++的重载有关,C++语言支持函数重载,C语言不支持函数重载,函数被C++编译器编译后在库中的名字与C语言的不同)
  2. 当extern不与“C”在一起修饰变量或函数时,如:extern int g_Int;它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块或其他模块中使用。记住它是一个声明不是定义!也就是说B模块(编译单元)要是引用模块(编译单元)A中定义的全局变量或函数时,它只要包含A模块的头文件即可,在编译阶段,模块B虽然找不到该函数或变量,但它不会报错,它会在连接时从模块A生成的目标代码中找到此函数。 ???????

 

2.static关键字的作用  

  • 修饰局部变量    

static修饰局部变量时,使得被修饰的变量成为静态变量存储在静态区。存储在静态区的数据生命周期与程序相同,在main函数之前初始化,在程序退出时销毁。(无论是局部静态还是全局静态)  

换种说法:

static局部变量 将一个变量声明为函数的局部变量,那么这个局部变量在函数执行完成之后不会被释放,而是继续保留在内存中,下次在调用该函数时仍维持上次的值,不论是否再初始化。

  • 修饰全局变量    

全局变量本来就存储在静态区,因此static并不能改变其存储位置。但是,static限制了其链接属性。被static修饰的全局变量只能被该包含该定义的文件访问(即改变了作用域)。   ???

表示一个变量在当前文件的全局内可访问

  • 修饰函数      

static修饰函数使得函数只能在包含该函数定义的文件中被调用。对于静态函数,声明和定义需要放在同一个文件夹中。  

  • 修饰成员变量       

用static修饰类的数据成员使其成为类的全局变量,会被类的所有对象共享,包括派生类的对象,所有的对象都只维持同一个实例。 因此,static成员必须在类外进行初始化(初始化格式:int base::var=10;),而不能在构造函数内进行初始化,不过也可以用const修饰static数据成员在类内初始化。  

  • 修饰成员函数      

用static修饰成员函数,使这个类只存在这一份函数,所有对象共享该函数,不含this指针,因而只能访问类的static成员变量。静态成员是可以独立访问的,也就是说,无须创建任何对象实例就可以访问。例如可以封装某些算法,比如数学函数,如ln,sin,tan等等,这些函数本就没必要属于任何一个对象,所以从类上调用感觉更好,比如定义一个数学函数类Math,调用Math::sin(3.14);还可以实现某些特殊的设计模式:如Singleton;

  • 最重要的特性:隐藏     ???

当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏。

  • 不可以同时用conststatic修饰成员函数。  

 C++编译器在实现const的成员函数的时候为了确保该函数不能修改类的实例的状态,会在函数中添加一个隐式的参数const this*。但当一个成员为static的时候,该函数是没有this指针的。也就是说此时const的用法和static是冲突的。我们也可以这样理解:两者的语意是矛盾的。static的作用是表示该函数只作用在类型的静态变量上,与类的实例没有关系;而const的作用是确保函数不能修改类的实例的状态,与类型的静态变量没有关系。因此不能同时用它们。

3.const的作用

  1. 定义变量为只读变量,不可修改
  2. 修饰函数的参数和返回值(后者应用比较少,一般为值传递)
  3. const成员函数(只需要在成员函数参数列表后加上关键字const,如char get() const;)可以访问const成员变量和非const成员变量,但不能修改任何变量。在声明一个成员函数时,若该成员函数并不对数据成员进行修改操作,应尽可能将该成员函数声明为const成员函数。
  4. const对象

只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数.即对于class A,有const A a;那么a只能访问A的const成员函数。而对于:A b;b可以访问任何成员函数。 使用const关键字修饰的变量,一定要对变量进行初始化

 const的作用主要有三点:

1:定义只读变量,即常量 

2:修饰函数的参数和函数的返回值 

3 修饰函数的定义体,这里的函数为类的成员函数,被const修饰的成员函数代表不修改成员变量的值


 const与static的区别:

  1. 释放时间:const定义的常量在超出其作用域之后其空间会被释放;而static定义的静态常量在函数执行后不会释放其存储空间
  2. 初始化:static静态成员变量不能在类的内部初始化。在类的内部只是声明,定义必须在类定义体的外部,通常在类的实现文件中初始化,如:double Account::Rate=2.25,而且前面不加static,以免与一般静态变量或对象相混淆,使用作用域运算符来表明它所属的类(类中的static变量是属于类的,不属于某个对象,它在整个程序的运行过程中只有一个副本)          

    const成员变量也不能在类定义处初始化,只能通过构造函数初始化列表进行初始化,并且必须有构造函数。

    const数据成员 只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。所以不能在类的声明中初始化const数据成员,因为类的对象没被创建时,编译器不知道const数据成员的值是什么

  3. 所属:上面第2点有提到:const属于对象,static属于类
  4. 目的:cosnt成员函数主要目的是防止成员函数修改对象的内容;  ||  static成员函数主要目的是作为类作用域的全局函数。不能访问类的非静态数据成员。类的静态成员函数没有this指针,这导致:(1)不能直接存取类的非静态成员变量,调用非静态成员函数,(2)不能被声明为virtual

4. 栈溢出几种情况及解决方案

一、局部数组过大。当函数内部的数组过大时,有可能导致堆栈溢出。

二、递归调用层次太多。递归函数在运行时会执行压栈操作,当压栈次数太多时,也会导致堆栈溢出。

三、指针或数组越界。这种情况最常见,例如进行字符串拷贝,或处理用户输入等等。

解决这类问题的办法有两个,      

一是增大栈空间; 二是改用动态分配,使用堆(heap)而不是栈(stack)。

猜你喜欢

转载自blog.csdn.net/qian27enjoy/article/details/82825281