C++中的struct和class有什么区别?

  1. 默认继承权限:class默认为私有继承;struct默认为共有继承
  2. 成员默认访问权限:class的成员默认是private权限;Private默认是public权限

除以上两点外,class和struct基本就是一个东西

C和C++有什么区别?

  1. 从机制上:C是面向过程的(但C也可以编写面向对象的程序);C++是面向对象的,提供了类(C++编写面向对象的程序比C容易)。
  2. 从适用的方向:C适合要求代码体积小的,效率高的场合,如嵌入式;C++适合更上层的,复杂的系统。 llinux核心大部分是C写的,因为它是系统软件,效率要求极高。
  3. 从名称上也可以看出,C++比C多了+,说明C++是C的超集;那为什么不叫C+而叫C++呢,是因为C++比C来说扩充的东西太多了,所以就在C后面放上两个+;于是就成了C++。

引用和指针的区别?

指针

指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作,即可以改变所指向的对象。
Note:程序中使用指针,程序的可读性差。

引用

引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
引用必须初始化。
引用初始化以后不能被该改变
不存在指向空值的引用,但是存在指向空值的指针

常引用

既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。

常引用声明方式:const 类型标识符 &引用名=目标变量名;

C++函数中值的传递方式有几种?

值传递,指针传递和引用传递

静态全局变量的作用域?

静态全局变量限制了其作用域,即只在定义该变狼的源文件内有效,在同一源程序的其它源文件中不能使用它

C++中Virtual与Inline的含义分别是什么?

在基类成员函数的声明前加上virtual关键字,意味着将该成员函数声明为虚函数。
inline与函数的定义体放在一起,使该函数称为内联。inline是一种用于实现的关键字,而不是用于声明的关键字。

虚函数的特点;

如果希望派生类能够重新定义基类的方法,则在基类中将该方法定义为虚方法,这样可以启用动态联编。

内联函数的特点;

使用内联函数的目的是为了提高函数的运行效率。
内联函数体的代码不能过长,因为内联函数省去调用函数的时间是以代码膨胀为代价的。
内联函数不能包含循环语句,因为执行循环语句要比调用函数的开销大

函数assert的作用?

断言assert是仅在debug版本起作用的用于检查“不应该“发生的情况。
程序员可以把assert看成一个在任何系统状态下都可以安全使用的无害测试手段

const与#define(宏)相比较,const有什么优点?

const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。
有些集成化的调试工具可以对 const 常量进行调试,但是不能对宏常量进行调试。

noexcept修饰符

noexcept表示其修饰的函数不会抛出异常。与throw()动态异常声明不同的是,在C++11中如果noexcept修饰的函数抛出了异常,编译器可以选择直接调用std::terminate()函数来终止程序的运行,这比基于异常机制的throw()在效率上会高一些。这是因为异常机制会带来一些额外的开销,比如函数抛出异常,会导致函数栈被依次地展开,并依帧调用在本帧中已构造的自动变量的析构函数,
语法上,有两种使用noexcept的形式:

一种是简单地在函数声明后加上noexcept关键字

  1. void excpt_func() noexcept

另一种是可以接受一个常量表达式作为参数

void excpt_func() noexcept (常量表达式)

不使用”if”,”?:”,”switch”或是其它判断条件,获取两个数中较大的数

((a+b)+abs(a-b))/2

C++如何打印出当前源文件的文件名及源文件的当前行号?

cout << __FILE__ ;
cout<<__LINE__ ;

FILELINE是系统预定义宏,这种宏并不是在某个文件中定义的,而是由编译器定义的

malloc/free和new/delete

malloc 与 free 是 C++/C 语言的标准库函数,new/delete 是 C++的运算符 (注意:不是库函数。)。它们都可用于申请动态内存和释放内存。
如果在申请动态内存时找不到足够大的内存块,malloc 和 new 将返回 NULL 指针,宣告内存申请失败。
**
对于非内部数据类型的对象而言,光用 maloc/free 无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。
由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于 malloc/free。
因此 C++语言需要一个能完成动态内存分配和初始化工作的运算符 new,以及一个能完成清理与释放内存工作的运算符 delete。
在new的过程中,编译器不会检查析构函数是否可以访问,因此可以通过将析构函数设置为private来使对象不能够直接创建,而是只能通过new来进行创建

C++不是类型安全的,因为不同类型的指针之间可以强制转换

如果通过C++判断操作系统是16位还是32位?

定义一个指针p,打印出sizeof(p),如果节后是4,则表示该操作系统是32位,打印结果是2,表示是16位。

C++头文件后缀名:.h .hpp .hxx

hpp,其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该hpp文件即可,无需再将cpp加入到project中进行编译。而实现代码将直接编译到调用者的obj文件中,不再生成单独的obj,采用hpp将大幅度减少调用 project中的cpp文件数与编译次数,也不用再发布烦人的lib与dll,因此非常适合用来编写公用的开源库。
编写hpp需要注意的是:

  • .h里面可以有using namespace std,而.hpp里则无。
  • 不可包含全局对象和全局函数。 由于hpp本质上是作为.h被调用者include,所以当hpp文件中存在全局对象或者全局函数,而该hpp被多个调用者include时,将在链接时导致符号重定义错误。要避免这种情况,需要去除全局对象,将全局函数封装为类的静态方法。
  • 类之间不可循环调用。
  • 不可使用静态成员。 静态成员的使用限制在于如果类含有静态成员,则在hpp中必需加入静态成员初始化代码,当该hpp被多个文档include时,将产生符号重定义错误。

C,C++文件常用后缀

C 中头文件 .h 源文件 .c
C++头文件 .h .hpp .hxx 源文件 .cpp .cc .cxx .C .c++

不同系统或编译器的定义

Unix: .C .cc .cxx .c
GNU C++: .C .cc .cxx .cpp .c++
Digital Mars: .cpp .cxx
Borland: .c++ .cpp
Watcom: .cpp
VC ++: .cpp .cxx .cc
Metrowerks CodeWarrior: .cpp .cp .cc .cxx .c++

编译器偏好

VS默认采用.cpp .h作为后缀
GCC默认采用.cc .h作为后缀

GCC 不同后缀含义

.c C语言源代码文件
.a 目标文件构成的档案库文件
.C .cc .cxx C++源代码文件
.h 程序所包含的头文件
.i 已经预处理过的C源代码文件
.ii 已经预处理过的C++源代码文件
.m Objective-C源代码文件
.o 编译后的目标文件
.s 汇编语言源代码文件
.S 经过预编译的汇编语言源代码文件

C++类内引入typedef

class MyClass
{
    public:
        typedef long INDEX;
};

上面的语句是放在了public段中,是可以在类外部使用,例如:MyClass::INDEX usercode
如果放在private段中,则只能在类内部使用。
引入仅能在类内部起作用的类型别名的初衷在于:通过限制该类型别名的作用域来防止冲突。比如同样表示长度,可能有的类中只需char即可,有的类中要用int,而又的类可能连long都嫌小。那么,一概起个别名叫”size”,不同的类中又不同的定义。
“类型别名”和变量、函数一样具有作用域。

整型5取反后的结果是-6

负数是按位取反再加一

C++三大特性

C++的三大特性是封装,继承和多态.
封装可以隐藏实现细节,使得代码模块化,继承可以扩展已存在的模块,它们目的都是为了:代码重用
封装的好处:

  • 将变化隔离
  • 便于使用
  • 提高重用性
  • 提高安全性

封装的原则:

  • 将不需要对外提供的内容都隐藏起来
  • 把属性都隐藏,提供公共方法对其访问

多态是为了实现另一个目的:接口重用。例如:打羽毛球,打篮球,打保龄球,这里的“打”就是多态。 多态性可以简单概括为“一个接口,多种实现”,是通过虚函数实现的。基类提供一个虚接口,其派生类重写这个接口,这样就构成了多态,简单说,就是某一类事物多种存在形态。
多态的体现:

  • 父类的引用指向了自己子类对象
  • 父类的引用也可以接收自己的子类对象

多态的前提:

  • 必须是类与类之间有关系。要么继承,要么实现
  • 存在覆盖

多态的好处:

  • 多态的出现大大的提高程序的扩展性

多态的弊端:

  • 提高了扩展性,但是只能使用父类的引用访问父类中的成员

识别函数或指针

void ((fp1)(int))[10]: fp1是一个指针,指向一个函数,这个函数的参数为int型,函数的返回值是一个指针,这个指针指向一个数组,这个数组有10个元素,每个元素是一个void型指针。
float((fp2)(int,int,int))(int): fp2是一个指针,指向一个函数,这个函数的参数为3个int型,函数的返回值是一个指针,这个指针指向一个函数,这个函数的参数为int型,函数的返回值是float型。
int((fp3)())10:fp3是一个指针,指向一个函数,这个函数的参数为空,函数的返回值是一个指针,这个指针指向一个数组,这个数组有10个元素,每个元素是一个指针,指向一个函数,这个函数的参数为空,函数的返回值是int型

多态类中的虚函数表

虚拟函数表是在编译期就建立了,各个虚函数这时被组织成了一个虚拟函数的入口地址的数组。而对象的隐藏函数—虚拟函数表指针是在运行期,也就是构造函数被调用时进行初始化的,这时实现多态的关键。

内存的分配方式有几种

  • 从静态存储区分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量
  • 从栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
  • 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

全局变量和局部变量的区别

生命周期不同

全局变量随主程序创建和创建,随主程序销毁而销毁;
局部变量在局部函数内部,甚至局部循环体等内部存在,退出就不存在; 内存中分配在全局数据

使用方式不同

通过声明后全局变量程序的各个部分都可以用到;局部变量只能在局部使用;分配在栈区

操作系统和编译器通过内存分配的位置来知道

全局变量分配在全局数据段并且在程序开始运行的时候被加载。局部变量则分配在堆栈里面 。

Heap和Stack的区别

Heap是堆,stack是栈。 Stack的空间由操作系统自动分配/释放,Heap上的空间手动分配/释放。
Stack空间有限,Heap是很大的自由存储区 C中的malloc函数分配的内存空间即在堆上,C++中对应的是new操作符。
程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行。


参考资料

https://blog.csdn.net/doo66/article/details/52208922