C++部分复习笔记上

C++语法复习

1. C++入门基础

缺省参数

  1. 半缺省参数必须从右往左依次来给出,不能间隔着给
  2. 缺省参数不能在函数声明和定义中同时出现
  3. 缺省值必须是常量或者全局变量
  4. C语言不支持(编译器不支持)

函数重载

函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这 些同名函数的形参列表**(参数个数 或 类型 或 类型顺序)不同**,常用来处理实现功能类似数据类型不同的问题。

原理:函数名的修饰规则 链接时需要通过函数名找到函数实现

gcc的函数修饰后名字不变。而g++的函数修饰后变成【_Z+函数长度 +函数名+类型首字母】

通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修 饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载

引用和指针

引用概念:引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空 间,它和它引用的变量共用同一块内存空间。

引用和指针的区别

从语法的角度来说引用是给已有的变量取别名,不开空间;指针是开空间存储对象的地址,指向对象

从使用角度来说:

  1. 引用定义的时候需要初始化,指针可以不初始化
  2. 上面推论:没有NULL引用,但有NULL指针, 引用比指针使用起来相对更安全
  3. 指针可以改变指向,引用不可以改变
  4. 有多级指针,但是没有多级引用
  5. sizeof指针和引用含义不一样
  6. 引用++和指针++表达的含义不一样
  7. 访问实体的方式不一样,指针需要显示解引用,引用由编译器处理

从底层实现的角度来说(最后)引用在底层实现上实际是有空间的,因为引用是按照指针方式来实现的

引用的使用场景

1.做参数

2.做返回值(注意使用安全,不要返回栈上的临时对象)

内联inline

C++建议使用 const enum inline 代替 宏, 内联/宏 和 函数对应

再来说说宏的缺点:

  1. 容易出错,符号优先级问题
  2. 不能调试,预处理阶段已经替换,看不到宏的具体处理逻辑
  3. 不够严谨,与类型无关,缺少类型检查

宏的优点:对于各种类型都适配,可以增加代码的复用性,当处理小型计算的任务时宏比函数调用的消耗更小

内联:以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率

inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会 用函数体替换函数调用,缺陷:可能会使目标文件变大(这一点和宏一样),优势:少了调用开销,提高程序运 行效率

inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同

inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址 了,链接就会找不到

nullptr

因为NULL在C++中可能是0也可能是((void*)0)

#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif
  1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入 的。
  2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
  3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。

2. 类和对象

面向对象和面向过程的区别?

面向对象更加注重:类和类之间的关系(如:栈的实现,容器适配器、迭代器统一(反向迭代器),算法通过迭代器获取容器的数据)

面向对象更加注重实现过程

**面向对象(Object-Oriented Programming, OOP)**是一种编程范式,它基于“对象”的概念,将数据和操作数据的方法组织在一起。在面向对象编程中,对象是类的实例,类定义了对象的属性(数据成员)和行为(方法)。对象可以互相通信,通过调用彼此的方法来完成任务。面向对象的四个核心原则是封装、继承、多态和抽象。
面向对象的主要特点

  1. 封装:隐藏对象的内部细节,只对外提供接口进行交互,保护数据的安全性。
  2. 继承:允许创建一个新类(子类)作为现有类(父类)的扩展,继承其属性和方法。
  3. 多态:同一方法可以根据调用它的对象类型表现出不同的行为。
  4. 抽象:通过抽象类或接口来定义通用行为,实现代码的重用和模块化。

面向过程(Procedural Programming): 面向过程编程更侧重于步骤和函数的组合来解决问题。程序被设计为一系列有序的步骤,每个步骤对应一个函数或子程序,这些函数直接操作数据。面向过程编程不强调对象的概念,而是以数据为中心,通过函数来处理数据。
面向对象与面向过程的区别

  1. 编程思路:面向对象是基于类和对象,通过对象之间的交互实现功能;面向过程是通过函数调用来完成任务序列。
  2. 封装性:面向对象封装的是数据和操作数据的方法,而面向过程主要封装的是功能逻辑。
  3. 结构与复用:面向对象支持继承和多态,使得代码更容易复用和扩展;面向过程的复用主要依赖函数和模块。
  4. 复杂性管理:面向对象更适合处理复杂的系统,因为它能更好地模拟现实世界中的实体和关系;面向过程则适用于简单的、线性的任务。

类大小的计算

内存对齐

和结构体的内存对齐规则一样

  1. 首元素位于0偏移量地址
  2. 对齐数 = 编译器的默认对齐数 和 对象大小 (取小)
  3. 整体大小等于最大对齐数的整数倍

空类大小(占位)

注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。

成员函数代码位于代码区,成员变量在实例化位置定义

struct 和 class 的区别

访问限定符、继承关系、兼容C语言

struct访问限定符默认public,class访问限定符默认private

struct默认public继承,class默认private继承

struct兼容C语言,在C语言中是结构体,在C++中可以定义成员函数方法,class不兼容C语言

this指针

C++编译器给每个“非静态的成员函数“增加了一个隐藏 的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量” 的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编 译器自动完成

特性

  1. this指针的类型:类类型 const*,即成员函数中,不能给this指针赋值
  2. 只能在“成员函数”的内部使用
  3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给 this形参。所以对象中不存储this指针
  4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递

this指针储存位置(寄存器ecx或调用位置的栈空间)

从概念上讲,当你调用一个非静态成员函数时,编译器会自动将调用该函数的对象的地址作为第一个隐式参数传递给该函数,这个地址就是this指针的值。在函数内部,你可以通过this指针来访问或修改对象的成员。

然而,this指针并不是存储在对象的内存布局中的一部分。它更像是函数调用的一个“附加”参数,由编译器在函数调用时自动处理。

在大多数实现中,当你调用一个成员函数时,编译器会生成一些额外的代码来设置this指针。这个指针通常会被存放在一个特殊的寄存器中,或者如果寄存器不可用,它可能会被压入调用栈中。但是,这些都是实现细节,并且在不同的编译器和平台上可能会有所不同

this指针可以为空吗,当你调用的成员函数内部不访问成员变量(就不会解引用报错)- 使用方式类似于静态成员函数

八个默认成员函数

  1. 构造和析构
  2. 拷贝构造和赋值
  3. 移动构造和移动赋值
  4. 取地址重载和const取地址重载(基本不用)

一般情况下,构造都是要自己实现的

深拷贝的类,需要提供拷贝构造、赋值重载和析构

移动构造和移动赋值,当上面三个是编译器默认生成的,编译器才会自己在生成

也就是说一般深拷贝的类需要自己提供移动构造和移动赋值

默认生成的,会对内置类型浅拷贝,对自定义类型调用其拷贝构造或赋值

对于默认移动构造和移动赋值,会对内置类型拷贝,自定义类型调用其对应的(自己实现的yes)移动构造,如果没有调用拷贝构造

初始化列表

特性:所有的构造初始化都会经过初始化列表

哪些成员必须要在初始化列表初始化?

  • 引用成员变量
  • const成员变量
  • 没有默认构造的自定义成员变量

无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数

初始化列表的初始化顺序是成员对象的声明顺序

运算符重载

目的是让自定义类型用运算符,增强可读性

哪些运算符不能重载 (.* .)

class Person
{
public:
	Person(double name = 1.1, int age = 0)
		:_name(name)
		, _age(age)
	{}

	void* operator new(size_t size) // new重载
	{}

	void operator delete(void* p) // delete重载
	{}
private:
	Test2 _name;
	int _age;
};

友元(了解)

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以 友元不宜多用

友元函数

友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在 类的内部声明,声明时需要加friend关键字

  • 友元函数可访问类的私有和保护成员,但不是类的成员函数
  • 友元函数不能用const修饰
  • 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
  • 友元函数的调用与普通函数的调用原理相同

友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员

  • 友元关系是单向的,不具有交换性
  • 友元关系不能传递
  • 友元关系不能继承

explicit关键字

构造函数对于单个参数或者除第一个参数无默认值其余均有默认值 的构造函数,还具有类型转换的作用

使用

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值