不定时总结cpp可能问到的考点。

  • 全局变量自动初始化,局部变量系统不会对其初始化
  • static变量,指在程序生命周期内保持局部(全局)变量的存在,仅仅初始化一次。当static修饰类数据成员的时候,会导致该类成员数据被所有的类所共享。
  • extern变量,extern 是用来在另一个文件中声明一个全局变量或函数。

指针和引用的区别

  • 引用是变量的别名,内部实现是只读指针
  • 指针可以是空指针,但是引用必须指向一块合法的内存
  • 引用一旦被初始化之后,就无法指向另一个对象
  • 引用必须在创建的时候进行初始化,指针则无所谓

####函数重载(静态多态)

指的是类中函数有着同样的函数名,但是函数的参数列表以及实现不同

多态(动态多态)

多态指的是调用多态成员时,会根据调用函数对象的不同,来执行不同的函数。如果使用普通函数,一个父类指针,指向子类对象。调用的函数仍然是父类函数。需要对这些函数声明virtual变量,使得父类指针能够正常的调用。

使用virtual定义函数,即为后期绑定,在函数执行的时候,才根据函数的主体来决定函数执行的定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
virtual int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};

对于这一类有虚函数的类来说,我们需要给父类加上虚析构函数,他的作用是在你删除父对象指针的时候,函数会调用子类的析构函数,对析构对象内存进行回收。

虚继承

1
class B:virtual public A{...}

虚继承解决多重继承问题中,父类二义性,冗余的问题。(菱形继承)

内存泄漏,内存溢出

内存泄露:本意是申请的内存空间没有被正确释放,导致后续程序里这块内存被永远占用(不可达),而且指向这块内存空间的指针不再存在时,这块内存也就永远不可达了,内存空间一直被占用。

内存溢出:内存越界,调用栈溢出等,栈内存不足的一种表现。

接口(纯虚函数)

即在类的成员函数中,有一些函数是纯虚函数,没有函数的实现,如下:

1
virtual int getArea() = 0;

当子类在继承的时候,需要实现该函数。

C++动态内存

栈内存:用于存储函数声明的变量,以及存储代码等,由系统自动分配

堆内存:在程序执行过程中,申请的内存空间,通常由程序员分配和回收(new,delete)

1
2
char* pvalue  = NULL;   // 初始化为 null 的指针
pvalue = new char[20]; // 为变量请求内存

设计模式

设计模式是一套被反复使用多数人知晓,经过分类的代码设计经验总结。

STL库

STL主要包括容器和算法,容器分为序列式容器和关联式容器

序列式容器不一定有序,但是可以被排序,如:vector,list,deque等

关联式容器,内部是一颗平衡二叉树,如set,map等等

迭代器提供了一种方法,使我们能够从头到尾遍历整个容器。

const

const修饰成员变量,该变量不能被修改,const 函数只能访问const成员函数,不能修改数据成员。

const在定义指针时的限制范围:

1
2
3
4
5
char greeting[] = 'hello';
char* p1 = greeting; // 指针,指针变量都可以改变
const char* p2= greeting; //指针是变量,指针所指的内容是const
char* const p3 = greeting; // 指针时const
const char* const p4 = greeting; // 指针以及所指的内容均是const

static变量

函数的static变量在执行此函数时进行初始化,类的static变量在类实例化之前初始化,分配内存。

  • 修饰普通变量:修改变量的存储区和声明周期,使变量存储在静态区,在main函数之前初始化
  • 修饰成员变量:所有对象共用一个成员实例,实例在对象生成之前就分类空间了
  • 修饰成员函数:static成员函数只能访问const变量,即对对象不做任何修改

this指针

  • this指针是隐含于每一个非静态成员函数中的特殊指针,他指向调用该成员函数的那个对象
  • this指针是const类型,可以代表当前的对象实例

inline内联函数

  • 内联函数直接在调用位置将代码展开,省去调用函数的开销,因此内联函数需要形式简单,不应该有for一类的操作。

  • 程序员无法确定函数是否真正内联,只能建议编译器内联,最后内联与否还是要编译器来决定。

  • inline可以修饰虚函数,但是只有在编译器知道调用对象是属于哪个类的时候,才可能发生。

struct和class

struct和class本质的区别在于class数据成员时private,struct数据成员时public的。

封装

对数据进行隐藏,同时提供数据访问接口。

堆和栈的生命周期

栈:由操作系统自动分配释放 ,存放函数的参数值,局部变量等。其操作方式类似于数据结构中的栈

堆: 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式类似于链表(new,delete操作)

内存泄漏,指针越界

动态内存分配时,空间在使用完之后未释放,一直占据着内存,称为内存泄漏。在new一块内存之后,需要用delete释放。

对指针赋值时,要注意指针赋值时的越界问题。

为了防止指针出现内存泄漏问题,可以将资源拷贝到auto_ptr,shared_ptr中,用这类资源管理器来管理资源。

成对的出现new和delete。

CPP代码执行的过程

预处理: 条件编译,宏替换等等

编译: 将处理后的语言转化成汇编语言

汇编: 将汇编语言转化为目标代码

链接: 链接目标代码,生成可执行文件

CPP创建类的时候,自动生成的代码

构造函数,析构函数,拷贝析构函数,赋值函数

智能指针

包括shared_ptrunique_ptr,weak_ptrauto_ptr。share_ptr指多个智能指针共享一个对象。unique_ptr独享一个对象,weak_ptr允许共享,但是不拥有对象。

Linux常见的指令

1
2
ps # 查看当前用户的进程
ps aux # aux 选项查看进程的 CPU 或内存使用量

Linux 的grep用法

grep 指令用于查找内容包含指定的范本样式的文件

1
grep test *file  # 查找file后缀的文件中,含有test的文件的那一行

Linux的find指令

1
2
find . -name "*jpg" # 找出当前路径,以及当前路径的子目录下所有图片
find . -type f # 将目前目录其其下子目录中所有一般文件列出

new,delete,malloc,free的区别

new,delete能够调用对象的构造函数或是析构函数,new,delete是C++的运算符不是库函数。

malloc,free是C++的库函数,用于申请和释放内存,仅使用于内部数据类型变量,无法调用对象的构造或析构函数。

delete:只调用一次析构函数

delete[]:会调用每一个对象的析构函数

构造函数,析构函数的调用顺序

定义一个对象时先调用基类的构造函数、然后调用派生类的构造函数

析构的时候恰好相反:先调用派生类的析构函数、然后调用基类的析构函数。

引用

给某个目标起别名,相当于直接对对象进行操作

重载和重写

重载是参数表不同,重写是子类覆盖了父类的方法