C++类和对象下篇

在这里插入图片描述

🐇

🔥博客主页: 云曦
📋系列专栏:[C++]

💨路漫漫其修远兮 吾将而求索
💛 感谢大家👍点赞 😋关注📝评论

文章目录

  • 📔1、再谈构造函数
    • 📰1.1、构造函数体赋值
    • 📰1.2、初始化列表
    • 📰1.3、explicit关键字
  • 📔2、static成员
    • 📰2.1、概念
    • 📰2.2、特性
  • 📔3、友元
    • 📰3.1、友元函数
    • 📰3.2、友元类
  • 📔4、内部类
  • 📔5、匿名对象
  • 📔6、拷贝对象时编译器的一些优化

📔1、再谈构造函数

📰1.1、构造函数体赋值

  • 在实例化对象时,编译器调用构造函数,在函数体内对成员变量进行赋值。
class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};
  • 虽然在实例化对象时给成员变量进行了赋值,但这并不是对成员变量的初始化,而是在初始化完后给成员变量赋值。

📰1.2、初始化列表

  • 初始化列表是以冒号开头“ : ” ,逗号间隔 " , ",每个成员变量后面紧跟一个括号()。
class Date
{
public:
	Date(int year, int month, int day)
		:_year(year)
		, _month(month)
		, _day(day)
	{}

private:
	int _year;
	int _month;
	int _day;
};
注意:
    1.每个成员变量初始化只能出现一次(初始化只能初始化一次)。
    2.类里面出现以下的成员变量,只能在初始化列表进行初始化。
	  (1)引用成员变量。
	  (2)const成员变量
  	  (3)自定义类型成员(且没有默认构造函数时)
class A
{
public:
	A(int a)
		:_a(a)
	{}

private:
	int _a;
};

class Date
{
public:
	Date(int year, int month, int day)
		:_year(year)
		, _month(month)
		, _day(day)
		,_ret(day)
		,_i(10)
		,aa(20)
	{}

private:
	int _year;
	int _month;
	int _day;
	int& _ret;     //引用 -> 语法规定:引用的对象必须初始化
	const int _i; //const成员变量 -> 语法规定const的类型必须初始化
	A aa;//没有默认构造 -> 成员变量是自定义类型时会去调用对应的默认构造,如果没有就会报错

};
(3)尽量使用初始化列表初始化,因为不管你用不用初始化列表,编译器都会走初始化列表。
class Time
{
public:
	Time(int hour = 10)
		:_hour(hour)
	{
		cout << "Time(int hour = 10)" << endl;
	}

private:
	int _hour;
};

class Date
{
public:
	Date(int year)
	{}

private:
	int _year;
	Time time_t;
};

int main()
{
	Date d1(2000);

	return 0;
}

在这里插入图片描述

(4)成员变量在类中的次序就是初始化列表的次序,与初始化列表的次序无关。
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
		: _day(day)
		, _month(month)
		,_year(year)
	{}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;

	return 0;
}

初始化列表的执行次序

  • 成员变量的次序与初始化列表次序不同会带来的问题
class stack
{
public:
	stack(size_t n)
		: _size(0)
		, _capacity(n)
		, _a((int*)malloc(sizeof(_a)* _capacity))
		
	{
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
	}

	void push(int val)
	{
		_a[_size] = val;
		_size++;
	}

	~stack()
	{
		free(_a);
		_a = nullptr;
		_size = 0;
		_capacity = 0;
	}

private:
	int* _a;
	size_t _size;
	size_t _capacity;
};

int main()
{
	stack st(10);
	st.push(1);
	st.push(2);
	st.push(3);

	//程序崩溃
	//原因:malloc开空间时,计算所需的字节是用_capacity进行计算的
	//但初始化列表的次序是跟着成员变量的次序走的,_capacity在_a的后面
	//那么先走的就是对_a进行开空间,这时_capacity没有初始化,是随机值
	//然后空间就有可能没有开对导致插入数据时程序崩溃

	return 0;
}
  • 所以大家在用初始化列表时,建议把初始化列表的次序和成员变量的次序写成一致,即实现了代码的可读性又避免了不必要的麻烦!

📰1.3、explicit关键字

  • 构造函数不止具有构造和初始化对象的功能,对于单个参数或多个参数只有第一个参数没有缺省值其余均有缺省值的情况,还具有类型转换的作用。(简单来说就是单参数的构造函数支持隐式类型转换)
class Date
{
public:
	Date(int year, int month = 1, int day = 1)
		: _day(day)
		, _month(month)
		,_year(year)
	{}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2023);

	//一个整型可以赋值给一个对象初始化
	//都是源自于单参数的构造函数支持隐式类型转换
	d1 = 2024;

	return 0;
}

在这里插入图片描述

  • explicit的作用就是不让他修饰的函数进行隐式类型转换
class Date
{
public:
	explicit Date(int year, int month = 1, int day = 1)
		: _day(day)
		, _month(month)
		, _year(year)
	{}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2023);
	d1 = 2024;
//编译报错: C2679: 二元“=”: 没有找到接受“int”类型的右操作数的运算符(或没有可接受的转换)

	return 0;
}

📔2、static成员

📰2.1、概念

(1)用stack修饰的类成员称为类的静态成员。
(2)用stack修饰的成员变量称为静态成员变量。
(3)用stack修饰的成员函数称为静态成员函数。
	注意:定义静态成员变量时,必须在类外进行初始化。
class A
{
public:
	A(int a = 0)
		:_a(a)
	{}

	int Get()
	{
		return _a;
	}

private:
	int _a;
};

class B
{
public:

	static void Print()  //静态成员函数
	{
		cout << _aa.Get() << endl;
		cout << _b << endl;
	}

private:
	static A _aa;//类的静态成员
	static int _b;//静态成员变量
};

//静态成员变量需要在类外初始化
int B::_b = 10;
A B::_aa = 20;

int main()
{
	A aa1;
	B::Print();//静态成员函数的调用

	return 0;
}
  • 那么static修饰的对象究竟有什么用了?
  • 这里有一个问题可以很好的讲解static的作用;
  • 实现一个类,计算出程序里创建出了多少个类对象
class A
{
public:
	A()
	{
		A::_count++;
	}

	A(const A& a)
	{
		A::_count++;
	}

	~A()
	{
		A::_count--;
	}

	static int GetCount()
	{
		return _count;
	}

private:
	static int _count;
};
这里分两种情况:
(1) 如果GetCount函数不是静态成员函数
int main()
{
	//3个类对象
	A aa1;
	A aa2(aa1);
	A aa3;

	//如果GetCount函数不是静态成员函数
	//编译报错:error C2352: 
	// “A::GetCount”: 调用非静态成员函数需要一个对象
	cout << A::GetCount() << endl; 
	//GetCount函数不是静态成员函数
	//多定义一个对象用这个对象.调用
	//打印时要-1因为这个a这个对象
	//是我们实例化出来调用GetCount静态成员函数的
	A a;
	cout << a.GetCount() - 1 << endl;

	return 0;
}
(2) 如果GetCount函数是静态成员函数
int main()
{
	//3个类对象
	A aa1;
	A aa2(aa1);
	A aa3;

	//如果GetCount函数是静态成员函数
	//即可以通过一个对象调用
	A a;
	cout << a.GetCount() - 1 << endl;

	//也可以用类名指定调用
	cout << A::GetCount() << endl;

	return 0;
}
  • 具体为何GetCount不是静态成员函数就不能用类名指定调用,且看static的特性。

📰2.2、特性

  1. 静态成员被所有类对象共享,不属于任何一个对象,存在静态区
  2. 静态成员变量必须在类外定义,定义时不加static关键字,类内只是声明
  3. 类的静态成员可以用 类名::静态成员 或者 对象.静态成员 进行访问
  4. 静态成员函数没有this指针,不能访问非静态成员
  5. 静态成员本质也是类的成员,受public、protected、private访问限定符限制
注意:
 (1) 静态成员函数不可以调用非静态成员函数。
 (2) 非静态成员函数可以调用静态成员函数
class A
{
public:
	A(int a = 0)
		:_a(a)
	{}

	static void func1()
	{
		func2();//编译报错:error C2352: 
		//“A::func2”: 调用非静态成员函数需要一个对象
	}

	void func2()
	{
		func1();//程序正常运行
	}



private:
	int _a;
};

int main()
{
	A aa(10);

	return 0;
}

📔3、友元

  • 友元提供了一种突破封装的方式,有时提供了便利,但友元会增加耦合度,破坏了封装,所以友元不宜多用。
  • 耦合度讲解:
    在这里插入图片描述
  • 友元分为友元函数友元类

📰3.1、友元函数

  • 在类和对象中篇,讲解operator<<和operator>>重载时,因为实现成成员函数时,this指针占用了第一个参数导致cout无法成为第一个参数,所以只能把operator<<和operator>>重载实现在类外,但类外无法访问到类内的成员变量,这时用友元解决了这里的问题。
class Date
{
	friend ostream& operator<<(ostream& out, Date& d);
	friend istream& operator>>(istream& in, Date& d);

public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};

ostream& operator<<(ostream& out, Date& d)
{
	out << d._year << "/" 
		<< d._month << "/" 
		<< d._day << endl;
	return out;
}

istream& operator>>(istream& in, Date& d)
{
	in >> d._year >> d._month >> d._day;
	return in;
}

int main()
{
	Date d1(2024,6,2);
	cout << d1 << endl;

	return 0;
}
  • 友元函数可以直接访问类内的私有成员,定义在类外的函数需要在类内声明且声明时需要加上friend关键字。
  • 注意:
    (1) 友元函数可以访问类内的私有和保护成员,但不能访问类内的成员函数
    (2) 友元函数不能用const修饰
    (3) 友元函数可以定义在类定义的任何地方,不受访问限定符限制。
    (4) 一个函数可以是多个类的友元函数
    (5) 友元函数的调用与普通函数调用是一样的

📰3.2、友元类

友元类的所有成员函数都可以访问另一个类中的非公有成员(公有成员类内类外都可以访问)。

  • 友元类的关系是单相的,不具有交换性
class A
{
//声明B类是A类的友元,B类可以访问A类的私有成员变量,
//但A类无法访问B类的私有成员
	friend class B;
public:
	A(int a = 100)
		:_a(a)
	{}

	void Print()
	{
		cout << "_a:" << _a << endl;
		cout << "_b:" << bb._b << endl;
		//编译报错:
		//error C2079: “A::bb”使用未定义的 class“B”
	}

private:
	int _a;
	B bb;
};

class B
{
public:
	B(int b = 100)
		:_b(b)
	{}

	void Print()
	{
		cout << "_a:" << aa._a << endl;
		cout << "_b:" << _b << endl;
	}

private:
	int _b;
	A aa;
};
  • 友元关系不能传递

举例:

  • 有A、B、C三个类,B类是A类的友元,C类是B类的友元,在A类里没有C类友元声明的情况下,C类不会是A类的友元。
class A
{
	friend class B;
public:
	A(int a = 0)
		:_a(a)
	{}


private:
	int _a;
};

class B
{
	friend class C;
public:
	B(int b = 0)
		:_b(b)
	{}

	void funB()
	{
		_aa._a;//B是A的友元,可以访问A类的私有成员变量
	}

private:
	int _b;
	A _aa;
};

class C
{
public:
	C(int c = 0)
		:_c(c)
	{}

	void funC()
	{
		_bbb._b;//C是B的友元,可以访问B类的私有成员变量
		_aaa._a;//C不是A的友元,不可以访问A类的私有成员变量
		//编译报错:
		//error C2248: “A::_a”: 
		//无法访问 private 成员(在“A”类中声明)
	}

private:
	int _c;
	A _aaa;
	B _bbb;
};
  • 友元关系不能继承
    这里关联到了继承,等到继承篇再和大家讲解。

📔4、内部类

  • 概念:在一个类内定义的类称为内部类,内部类就是一个独立的类,它不属于外部类,外部类对内部类没有任何优越的访问权限。
  • 注意:内部类天生就是外部类的友元,内部类可以访问外部类的私有成员变量,但外部类无法访问内部类的私有成员变量。
class A
{
public:
	class B
	{
	public:
		B(int b = 0)
			:_b(b)
		{}

		void funB(const A& aa)//B天生是A的友元
		{
			aa._a;
		}

	private:
		int _b;
	};

	A(int a = 0)
		:_a(a)
	{}

private:
	int _a;
};
  • 特性:
    1. 内部类可以定义在外部类的public、protected、private都是可以的。
class A
{
public:
	class B
	{
	public:
		void funa(const A& aa)
		{
			aa._a;
		}
	protected:
		void funb(const A& aa)
		{
			aa._a;
		}
	private:
		void func(const A& aa)
		{
			aa._a;
		}

	private:

		int _b;
	};

private:
	int _a;
};
  1. 内部类可以访问外部类的static修饰的成员,不用指定类名或外部类的对象。
class A
{
public:
	class B
	{
	public:
		void func(const A& aa)
		{
			cout << aa._a << endl;
			cout << _n << endl;
		}

	private:
		int _b;
	};

private:
	int _a;
	static int _n;
};

int A::_n = 0;
  1. sizeof(外部类)不会计算内部类,和内部类没有任何关系。
class A
{
public:
	class B
	{
	public:
		void func(const A& aa)
		{
			cout << aa._a << endl;
		}

	private:
		int _b;
	};
	
private:
	int _a;//4字节
};


int main()
{
	cout << sizeof(A) << endl;//编译通过,打印4

	return 0;
}

📔5、匿名对象

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a = 0)" << endl;
	}

	~A()
	{
		cout << "~A()" << endl;
	}

private:
	int _a;
};

int main()
{
	A aa1(10);//实例化对象

	//匿名对象
	//匿名对象的特点就是不用给对象起名字
	//且匿名对象的生命周期只在这一行
	//过了这一行就会调用析构函数
	A(20);

	A aa2(1);

	return 0;
}
  • 匿名对象的使用场景
class A
{
public:
	int A_func(int n)
	{
		//进行累加之类的操作...
		return n;
	}
};

int main()
{
	A().A_func(10);

	return 0;
}

STL篇章还会有其他的使用场景。

📔6、拷贝对象时编译器的一些优化

  • 在传参和传返回值时,现在的编译器一般都会做的一些优化,这些优化在一些场景下还很有用。
  • **注意:**我这里用的是vs2022来演示的,不同的编译器不同,可能会优化也可能不优化。
  • 这个优化就是:在同一个表达式内:
  1. 构造+构造 -> 构造(两次构造会优化成一次构造)
  2. 构造+拷贝构造->构造(一次构造和一次拷贝构造会优化成一次构造)
  3. 拷贝构造+拷贝构造->拷贝构造(两次拷贝构造会优化成一次拷贝构造)
class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a)" << endl;
	}

	A(const A& a)
	{
		cout << "A(const A& a)" << endl;
		_a = a._a;
	}

	A& operator=(const A& a)
	{
		cout << "A& operator=(const A& a)" << endl;
		if (this != &a)
		{
			_a = a._a;
		}

		return *this;
	}

	~A()
	{
		cout << "~A()" << endl;
	}

private:
	int _a;
};
  • 场景1
void func1(A aa)
{}

void scene1()
{
	//单参数的构造函数支持隐式类型转换
	//隐式类型转换,构造一个临时对象
	//用这个临时对象再去拷贝构造给aa
	//构造+拷贝构造->优化成一个构造
	func1(10);
}

在这里插入图片描述

  • 场景3

A func2()
{
	A aa(10);

	return aa;
}

void scene2()
{
	//func2函数的aa对象是一个局部对象
	//传值返回这个对象会拷贝构造出一个临时对象返回
	//返回的临时对象再去拷贝构造a2
	//连续的拷贝构造+拷贝构造->被优化成一次拷贝构造
	A a2 = func2();
}
  • 场景3
A func2()
{
	A aa(10);

	return aa;
}

void scene3()
{
	//传值返回,拷贝构造一个临时对象
	//再用这个临时对象去赋值拷贝给a3
	//拷贝构造 + 赋值拷贝 -> 无法优化
	A a3;
	a3 = func2();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/673521.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

链表算法题(OJ刷题超详细讲解)

1.返回倒数第K个节点&#xff0c; OJ链接&#xff1a;返回倒数第K个节点 本题有很多种解法&#xff0c;例如创建数组&#xff0c;或者将原链表反转等等&#xff0c;这里们使用快慢指针&#xff0c;只需要遍历一遍链表&#xff0c;并且空间复杂度为O(1)&#xff0c;时间复杂度为…

【C++杂货铺】unordered系列容器

目录 &#x1f308; 前言&#x1f308; &#x1f4c1; unordered系列关联式容器 &#x1f4c1; 底层结构 &#x1f4c2; 哈希概念 &#x1f4c2; 哈希冲突 &#x1f4c2; 哈希函数 &#x1f4c2; 哈希冲突解决 &#x1f4c1; 模拟实现 &#x1f4c1; 总结 &#x1f308; 前…

Tailwindcss Layout布局相关样式及实战案例,5万字长文,附完整源码和效果截图

aspect 相关样式类 基础样式 ClassPropertiesaspect-autoaspect-ratio: auto;aspect-squareaspect-ratio: 1 / 1;aspect-videoaspect-ratio: 16 / 9; 案例&#xff1a;引入B站视频 Use the aspect-* utilities to set the desired aspect ratio of an element. 使用’ asp…

k8s学习--ConfigMap详细解释与应用

文章目录 一 什么是configmapConfigMap 的好处ConfigMap 的限制 二.创建ConfigMap的4种方式1.在命令行指定参数创建2.在命令行通过多个文件创建3.在命令行通过文件提供多个键值对创建4.YAML资源清单文件创建 三 configmap的两种使用方法1.通过环境变量的方式传递给pod2.通过vol…

Java(十二)---认识异常

文章目录 前言1. 异常的概念与体系结构1.1.异常的概念1.异常的体系1.3 异常的分类 2. 异常的处理2.1 防御式编程2.2 异常的抛出2.3 异常的捕获2.3.1 异常声明throws2.3.2 try-catch捕获并处理2.3.3 finally 2.4 异常的处理流程 3. 自定义异常类 前言 这一篇就是咱们学习JavaSE…

学习笔记——网络参考模型——TCP/IP模型(传输层)

四、TCP/IP模型-传输层 一、TCP 1、TCP定义 TCP(Transmission Control Protocol&#xff0c;传输控制协议)∶为应用程序提供可靠的面向连接的通信服务。目前&#xff0c;许多流行的应用程序都使用TCP。 连接&#xff1a;正式发送数据之前&#xff0c;提前建立好一种虚拟的&…

String常用操作

String常用方法 构造字符串 常用的构造字符串有3种&#xff1a; 1.直接赋值String s "abcd"; 2.实例化调用构造方法String s new String("abcd"); 3.实例化传字符数组 char[] ch {a,b,c,d}; String s new String(ch);字符串比较 比较 比较的是两个…

40.8K开源交流社区平台:Discourse

Discourse&#xff1a; 开放源代码&#xff0c;打造社区讨论的自由家园- 精选真开源&#xff0c;释放新价值。 概览 Discourse是一个完全开源的社区平台&#xff0c;为那些希望完全控制自己网站运行方式和地点的组织和个人提供服务。经过十多年的实战考验&#xff0c;Discours…

索引 ---- mysql

目录 1. 索引 1.1 概念 1.2 作用 1.3 使用场景 1.4 使用 1.4.1查看索引 1.4.2 创建索引 1.4.3 删除索引 1.5 注意事项 1.6 索引底层的数据结构 (面试经典问题) 1. 索引 1.1 概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。可以对表中的…

数据库(18)——DCL权限控制

MySQL常用权限 权限说明ALL,ALL PRIVILEGES所有权限SELECT查询数据INSERT插入数据UPDATE修改数据DELETE删除数据ALTER修改表DROP删除数据库/表/视图CREATE创建数据库/表 DCL语法 查询权限 SHOW GRANTS FOR 用户名主机名; 查询hello的权限 SHOW GRANTS FOR hellolocalhost; 授…

方法重写

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 基类的成员都会被派生类继承&#xff0c;当基类中的某个方法不完全适用于派生类时&#xff0c;就需要在派生类中重写父类的这个方法&#xff0c;这和…

pycharm链接auto al服务器

研0提前进组&#xff0c;最近阻力需求是把一个大模型复现&#xff0c;笔者电脑18年老机子&#xff0c;无法满足相应的需求。因此租用auto dl服务器。本文记录自己使用pycharm&#xff08;专业版&#xff09;链接auto dl期间踩过的坑。 1.下载pycharm专业版 这一步不解释了&am…

ESP32 WSL环境搭建

克隆代码 代码链接&#xff1a;https://gitee.com/EspressifSystems/esp-idf 克隆代码&#xff1a; git clone https://gitee.com/EspressifSystems/esp-idf 安装环境 cd esp32 /usr/bin/python3 ./esp-idf/tools/idf_tools.py 这里可能需要安装比较久&#xff0c; 有些需要…

基于51单片机的俄罗斯方块

一.硬件方案 本设计采用STC89C52RC单片机作为系统的芯片&#xff0c;实现人机交互、娱乐等功能。选用LCD12864实现俄罗斯方块游戏界面、图形显示&#xff1b;选用独立按键实现游戏控制。本设计实现的基本功能是&#xff1a;用按键控制目标方块的变换与移动&#xff1b;消除一行…

Java 多线程创建:三种主要方法

多线程编程是Java中一个重要的技术点&#xff0c;它允许程序并行执行多个任务&#xff0c;从而提高程序的执行效率。本文将详细介绍在Java中创建多线程的三种主要方法&#xff1a;继承Thread类、实现Runnable接口以及使用Callable和Future接口。 1. 继承 Thread 类 继承Threa…

python_将二维列表转换成HTML格式_邮件相关

python_将二维列表转换成HTML_邮件相关 data[["理想","2"],["理想2","3"]]def list_to_html_table(data):"""将二维列表转换为HTML表格格式的字符串。参数:data -- 二维列表&#xff0c;表示表格的数据。返回:一个字符…

最新国内AI工具(ChatGPT4.0、GPTs、AI绘画、文档分析使用教程)

如何利用AI提高内容生产效率&#xff1f; AI&#xff08;人工智能&#xff09;正以惊人的速度改变我们的生活方式&#xff0c;尤其是在内容生产领域。作为一名创作者&#xff0c;你可能会发现自己在面对海量信息时无从下手&#xff0c;或者在紧迫的截止日期前感觉力不从心。这时…

汽车数据应用构想(二)

一直说数据价值场景&#xff0c;啥叫有价值&#xff1f;啥样的场景有价值&#xff1f;按互联网的价值观来看&#xff0c;用户的高频需求就是价值。用户也许不会付费&#xff0c;但只要他天天用&#xff0c;那就是流量&#xff0c;就是用户黏性&#xff0c;就是价值&#xff01;…

【Qt】对话框

文章目录 1 :peach:对话框介绍:peach:2 :peach:对话框的分类:peach:2.1 :apple:模态对话框:apple:2.2 :apple:非模态对话框:apple:2.3 :apple:混合属性对话框:apple: 3 :peach:Qt 内置对话框:peach:3.1 :apple:消息对话框 QMessageBox:apple: 1 &#x1f351;对话框介绍&#x…

【一刷《剑指Offer》】面试题 29:数组中出现次数超过一半的数字

力扣对应题目链接&#xff1a;169. 多数元素 - 力扣&#xff08;LeetCode&#xff09; 牛客对应题目链接&#xff1a;数组中出现次数超过一半的数字_牛客题霸_牛客网 (nowcoder.com) 核心考点 &#xff1a; 数组使用&#xff0c;简单算法的设计。 一、《剑指Offer》对应内容 二…