c++ 一些常识 1

前言

今天开始复习C++相关的语法内容,加以简单的记录。

关于智能指针

智能指针的作用是管理一个指针,避免程序员申请的内存在函数结束时忘记释放造成内存泄漏。智能指针是一个类,超出类的作用域,类会自动调用析构函数,析构函数会自动释放资源。
有四种智能指针

  • auto_ptr(c++11已抛弃),用于实现独占式的概念,赋值之后会剥夺用于赋值的智能指针的所有权,但是之后访问它会报错。
  • unique_ptr,用于替换auto_ptr,保证同一时间只能有一个智能指针可以指向该对象,赋值操作会报错。
  • shared_ptr,实现共享式概念,多个shared_ptr可以指向相同对象,采用引用计数,所指对象会在最后一个引用销毁时释放。
  • weak_ptr,不控制对象生命周期的智能指针,它指向一个shared_ptr管理的对象,不会影响引用计数,提供一种对管理对象的访问手段。

c++ 内存分布(堆和栈的区别)

  • 栈。由编译器分配和回收,存放局部变量和函数参数。连续的内存空间。从高地址向低地址扩展,空间较小。
  • 堆。由程序员管理,需要调用new malloc delete free 进行分配和回收。是不连续的内存空间,由低地址向高地址扩展,空间较大。频繁的申请和释放容易造成内存碎片。
  • 全局/静态存储区,分为初始化和未初始化两个相邻区域,存储初始化和未初始化的全局和静态变量。
  • 常量存储区,存储常量
  • 代码区,存放程序代码

const

  • 修饰基本数据类型,表示变量只读,使用时不可改变值。
  • 修饰指针,如果const在星号左侧,表示指针所指变量只读,如果const在星号右侧,表示指针的值只读。
  • 修饰函数参数,在调用函数时用相应的变量初始化const修饰的参数。
  • 修饰函数返回值
  • 修饰类的成员变量,在所在对象的生命周期内是常量。
  • 修饰类的成员函数,常量的对象可以调用cosnt成员函数,不可以调用非const成员函数,const成员函数不可以通过this指针改变指向对象的值。需要修改时,可以用mutable修饰需要修改的成员变量。
  • c中的const仅仅从编译层限定不允许对变量进行修改,在运行时并非真正的常量。c++在编译时将const常量加入符号表,以后遇到会从符号表中查找,无法修改。

static

  • 修饰全局变量或全局函数,限制其作用域,只能在本文件内可见
  • 修饰局部变量,扩大其生命周期,不会随着作用域退出而消亡。
  • 修饰类成员函数,静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。可以通过类或对象调用
  • 修饰成员变量,表示属于整个类,存储空间只有一个副本。可以通过类或对象访问。静态非常量数据成员需要在类外定义和初始化。

c和c++区别

  • c是面向过程的,c++增加了面向对象编程理念,包括封装、继承、多态。
  • c++基本上完全完全兼容c,c是c++的一个子集。
  • c++支持运算符重载、异常机制、泛型编程。

重写和重载

  • 重载是指同一作用域内,函数的名称相同,参数列表不同时,可以根据调用参数列表决定调用哪个函数。
  • 重写是子类中重新定义父类中除了函数体外完全相同的虚函数。可以根据调用对象的实际类型决定调用的是子类还是父类中的虚函数。
  • 隐藏,子类重新定义父类中非virtual的同名函数。参数列表和返回类型都可以不同。

编译过程

文本 a.c --预处理-- 修改后的文本 a.i – 编译-- 汇编文本a.s --汇编–目标文件 a.o --链接 – 可执行文件 a

内存泄漏

用动态存储分配函数开辟的空间,在使用完毕后未释放,导致一直占据该内存单元。
内存分配后要及时初始化,new\malloc 分配的内存及时delete/free,用智能指针保管动态内存。对指针赋值前保证没有位置是孤立的。释放结构化元素时需要先遍历自内存并释放再释放主内存。

指针与引用的异同

相同点

  • 都是地址的概念
  • 都是指向一块内存,指针的内容是内存地址,引用是某块内存的别名
  • 应用在内部是借助指针实现的,某些情况下可以代替指针。

不同点

  • 指针是一个实体,引用是个别名。
  • 引用智能在定义时被初始化一次,之后不可变,指针可以指向不同的对象
  • 引用不能为空,指针可以为空
  • sizeof 指针是指针的大小,sizeof引用是其引用对象的大小
  • 引用具有更好的可读性和实用性

extern关键字

可以在一个文件中引用另一个文件中定义的全局变量或全局函数

extern “C”

告诉c++编译器用c规则编译指定代码

左值引用和右值引用

左值引用就是通常所讲的引用。
右值引用用来绑定到右值,本来会销毁的右值生命周期延长到它的右值引用的生命周期

面向对象三大特性

  • 封装。一个类就是封装了数据和操作这些数据的代码的逻辑实体,在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问,通过这种方,对象内部数据被提供了不同级别的保护
  • 继承,指可以让某个类型的对象获得另一个类型对象的属性的方法。可以使用现有类的所有功能,在无需重新编写原有类的情况下对这些功能进行扩展。
  • 多态,向不同的对象发送同一个消息,不同的对象接收时会产生不同的行为。即一个接口可以实现多种方法。

多态的实现

动态多态是子类重写父类中虚函数来实现的,在运行期决定调用哪个函数。在基类的函数前加上virtual,在子类中重写该函数,运行时将会根据对象的实际类型来调用相应函数。
静态多态就是重载,借助编译器为函数生成符号表的不同。

虚函数实现原理

当一个类中包含虚函数时,编译器会为该类生成一个虚函数表, 保存该类中的虚函数地址。子类继承基类,也会有虚函数,编译器也会为子类生成自己的虚函数表,当定义一个子类对象时,编译器检测该类型有虚函数,就会生成一个虚函数指针,指向该类型的虚函数表。当调用虚函数时,就会根据所指真正对象的虚表指针去寻找虚函数地址。

4种强制转换

  • static_cast 若两个类型在一个方向上可以进行隐式类型转换时使用这种作为显示类型转换
  • dynamic_cast 在有多态关系的父子指针或引用之间转换
  • const_cast 去住或添加const属性
  • reinterpret_cast 在指针与指针、指针与整数之间转换

析构函数写成虚函数的原因

为了降低内存泄漏的可能性。
如果基类的析构函数定义成虚函数,那么编译器就可以根据实际对象,执行派生类的析构函数,再执行基类的析构函数,成功释放内存。

构造函数为什么不能是虚函数

虚函数是通过实例化之后对象的虚表指针去找到虚函数地址进行调用,执行构造函数前虚表指针还不存在,无法找到对应的虚函数表。

构造函数或者析构函数中调用虚函数会怎样

不应该在构造或析构函数中调用虚函数。不会带来所想要的结果。构造派生类的基类部分时编译器会认为这是基类对象,派生类部分未定义,派生类执行派生类的析构函数时,派生类部分未定义,此时不可能调用到派生类重写方法。

构造、析构函数的执行顺序

构造函数顺序
基类构造函数、成员对象构造函数、派生类构造函数

析构函数顺序
派生类析构函数、成员对象析构函数、基类析构函数

纯虚函数

希望只继承接口并提供实现。
申明一个纯虚函数目的就是让派生类值继承函数 的接口,而且派生类必须提供一个这个纯虚函数的实现,否则这个含有纯虚函数的类将是抽象类,不能进行实例化。

静态绑定和动态绑定

静态绑定,绑定的是静态类型,所对应的函数或属性依赖于对象的静态类型,发生在编译期间。
动态绑定,绑定的是动态类型,所对应的函数或属性依赖于对象的动态类型,发生在运行期间。
比如说虚函数是动态绑定的,非虚函数是静态绑定的,雀神参数值也是静态绑定的。

深拷贝和浅拷贝

需要拷贝操作时,比如拷贝构造、拷贝赋值。在未显示定义拷贝构造函数的情况下,系统默认的拷贝函数是浅拷贝,能够完成成员的一一复制,在数据成员没有指针时,浅拷贝是可行的。
当数据成员有指针时,如果采用简单的浅拷贝,则两个对象的指针指向同一个地址,当对象销毁时会调用两次析构函数,造成野指针问题。此时必须采用深拷贝,深拷贝会在堆内存中另外申请内存空间来存储数据。

什么情况下调用拷贝构造

对象以值传递的方式传入函数体,需要执行拷贝构造函数创建一个零时对象压入栈空间。
对象以值传递的方式从函数返回,需要执行拷贝构造函数创建一个临时对象作为返回值。
一个对象通过另一个对象初始化。

为什么拷贝构造必须引用传递

为了防止递归调用。如果是值传递,那么为了创建传递给拷贝构造函数的参数的临时对象,又要调用一次拷贝构造函数,递归下去。

define和typedef的区别

  • 执行时间不同,typedef 在编译阶段有效,有类型检查功能,define发生在预处理阶段。
  • typedef用于定义类型的别名,define还可以定义常量、变量、编译开关等
  • 作用域不同,typedef有自己的作用域,define没有。

后记

学不可以已。每天都要学习新知识或者复习旧知识,要么得到要么丢掉。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值