C++
1. C++从源文件到可执行文件的步骤
(1) 预处理:处理所有的预编译指令,生成.i文件。
(2) 编译:经过词法分析、语法分析、语义分析和优化后生成汇编语言。生成.s文件
(3) 汇编:将编译阶段生成的汇编文件转化成机器码,生成可重定位目标文件。生成.o文件
(4) 链接:将多个目标文件及所需要的库链接成最终的可执行目标文件。生成.out文件
2. C++多态
1)多态的方式有几种
(1)静态多态(重载,模板)
是在编译的时候,就确定调用函数的类型。
(2)动态多态(覆盖,虚函数实现)
在运行的时候,才确定调用的是哪个函数,动态绑定。运行基类指针指向派生类的对象,并调用派生类的函数。
2)多态是什么
允许将子类类型的指针赋值给父类类型的指针。多态在C++中都是通过虚函数实现的
虚函数实现原理:虚函数表和虚函数指针。
纯虚函数: virtual int fun() = 0;
3)虚函数表和虚指针
虚表是一个指针数组,其中存储了类中所有虚函数的地址。每个类都有一个虚表,其中存储了该类的所有虚函数的地址。当一个类被继承时,子类会继承父类的虚表,并在其后面添加自己的虚函数地址。这样,当子类对象调用父类的虚函数时,会通过父类对象的虚指针找到父类的虚表,然后调用相应的函数。而当子类对象调用自己的虚函数时,会通过子类对象的虚指针找到子类的虚表,然后调用相应的函数。
3. C++访问权限控制符
public 公有成员 基类、派生类、友元、外部都可以访问
protected 保护成员 基类、派生类、友元可以访问
private 私有成员 基类、友元可以访问
对于继承来说:
1、public 方式继承
派生类能访问基类的public, protected成员,继承过来权限不变,派生类对象只能访问基类public成员。
2、protected方式继承
派生类可以访问基类的public, protected,继承过来都变成了protected,派生类对象啥都不能访问。
3、private方式继承
派生类可以访问基类的public, protected成员,继承过来之后变成自己私有的。 派生类的对象啥都不能访问。
4. C++11的新特性
- 自动类型推导(auto);
- 智能指针(std::unique_ptr、std::shared_ptr、std::weak_ptr);
- lambda表达式;
- 右值引用(&&);
- constexpr关键字;
- 变长参数模板(Variadic Templates);
- 新的整数类型long long int;
- std::function和std::bind等封装使函数调用更加方便。
- nullptr空指针
5. 智能指针
1)为什么要用智能指针
从较浅的层面看,智能指针是利用了一种叫做RAII(资源获取即初始化)的技术对普通的指针进行封装,
这使得智能指针实质是一个对象,行为表现的却像一个指针。
作用当然很明显,防止忘记调用delete,当然还有另一个作用,
也指出来了,就是异常安全。在一段进行了try/catch的代码段里面,即使你写入了delete,也有可能因为发生异常,程序进入catch块,从而忘记释放内存,这些都可以通过智能指针解决。
但是智能指针还有一重更加深刻的含义,就是把 所说的value语义转化为reference语义。
C++和Java有一处最大的区别在于语义不同,在Java里面下列代码:
Animal a = new Animal();
Animal b = a;
你当然知道,这里其实只生成了一个对象,a和b仅仅是把持对象的引用而已。但在C++中不是这样,
Animal a;
Animal b;
这里确实就是生成了两个对象。
在编写OOP程序时,value语义带来太多的困扰,例如TCP连接中我封装一个accept函数接收请求,那么应该是这样的:
Socket accept();
这就带来一个问题,采用对象做返回值,这里面有一个对象的复制的过程,但是Socket因为某些原因,我让他继承了boost::noncopyable,总之就是Socket失去了复制和赋值的能力,那么该怎么办?
我们首先想到指针,在accept内部new生成一个对象,然后返回指针。但是问题更多,这个对象何时析构? 过早析构,程序发生错误,不进行析构,又造成了内存泄露。
这里的解决方案就是智能指针,而且是引用计数型的智能指针。
typedef boost::shared<Socket> SocketPtr;
SocketPtr accept();
这样外部就可以用智能指针去接收,那么何时析构?当然是引用计数为0,也就是我不再需要这个Socket的时候析构。
这样,我们利用了SockerPtr,实现了跟Java类似的Reference语义。
还有一个例子,Java中往容器中放对象,实际放入的是引用,不是真正的对象,而C++在vector中push_back采用的是值拷贝,如果想实现Java中的引用语义,就应该使用智能指针,可以参考《C++标准库程序》(侯捷/孟岩 译)的第五章讲容器的部分,有一节叫做“用Value语义实现Reference语义”
2)shared_ptr的循环引用问题
虽然智能指针会减少内存泄漏的可能性,但是如果使用智能指针的方式不对,一样会造成内存泄漏。比较典型的情况是循环引用问题,比如这段代码
class B; // 前置声明
class A {
public:
shared_ptr<B> ptr;
};
class B {
public:
shared_ptr<A> ptr;
};
int main()
{
while(true) {
shared_ptr<A> pa(new A());
shared_ptr<B> pb(new B());
pa -> ptr = pb;
pb -> ptr = pa;
}
return 0;
}
这个程序中智能指针的引用情况如下图
上图中,class A和class B的对象各自被两个智能指针管理,也就是A object和B object引用计数都为2,为什么是2?
分析class A对象的引用情况,该对象被main函数中的pa和class B对象中的ptr管理,因此A object引用计数是2,B object同理。
在这种情况下,在main函数中一个while循环结束的时候,pa和pb的析构函数被调用,但是class A对象和class B对象仍然被一个智能指针管理,A object和B object引用计数变成1,于是这两个对象的内存无法被释放,造成内存泄漏,如下图所示
解决方法
解决方法很简单,把class A或者class B中的shared_ptr改成weak_ptr即可,由于weak_ptr不会增加shared_ptr的引用计数,所以A object和B object中有一个的引用计数为1,在pa和pb析构时,会正确地释放掉内存
3)weak_ptr的lock()
lock()函数通过expired()来判断是否对象是否存在,如果expired()返回true,说明该对象已经被析构,此时只会返回一个空的shared_pte;如果expired()返回false,说明此对象shared_pte的引用次数大于0,此时会返回一个指向该对象的shared_ptr
6. C++中的static关键字
1)static关键字
(1)局部变量
静态局部变量使用static修饰符定义,即使在声明时未赋初值,编译器也会把它初始化为0。且静态局部变量存储于进程的全局数据区,即使函数返回,它的值也会保持不变。
(2)全局变量
普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。
静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。
在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用。
(3)函数
函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数。其特性如下:
- 静态函数只能在声明它的文件中可见,其他文件不能引用该函数
- 不同的文件可以使用相同名字的静态函数,互不影响
非静态函数可以在另一个文件中直接引用,甚至不必使用extern声明
(4)静态成员变量
静态成员变量不能在类中定义,在定义时分配存储空间
同全局变量相比,使用静态数据成员有两个优势:
- 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性
- 可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能
(5)静态成员函数
与静态数据成员类似,静态成员函数属于整个类,而不是某一个对象,其特性如下:
静态成员函数没有this指针,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数
出现在类体外的函数定义不能指定关键字static
非静态成员函数可以任意地访问静态成员函数和静态数据成员
2)静态变量的初始化顺序问题
如果静态变量在同一个编译单元,则他们的初始化顺序取决于他们声明的顺序
但是如果静态变量在不同的编译单元,则会出现初始化顺序问题
(59条消息) Effective C++笔记(3)—条款4分析_NearXDU的博客-CSDN博客
Linux
1. malloc中的brk和mmap
(60条消息) Linux内存分配小结--malloc、brk、mmap_mmap申请的内存和堆内存有什么区别_gfgdsg的博客-CSDN博客
标签:八股,函数,对象,更新,面试,C++,静态,ptr,指针 From: https://www.cnblogs.com/lihaoxiang/p/17435810.html