C++【个人笔记1】

1.C++的初识

1.1 简单入门

#include<iostream>
using namespace std;
int main() {cout << "hello world" << endl;return 0;
}
  1. #include<iostream>; 预编译指令,引入头文件iostream.
  2. using namespace std; 使用标准命名空间
  3. cout << “hello world”<< endl; 和printf功能一样,输出字符串”hello wrold”

问题1:c++头文件为什么没有.h?

在c语言中头文件使用扩展名.h,将其作为一种通过名称标识文件类型的简单方式。但是c++得用法改变了,c++头文件没有扩展名。但是有些c语言的头文件被转换为c++的头文件,这些文件被重新命名,丢掉了扩展名.h(使之成为c++风格头文件),并在文件名称前面加上前缀c(表明来自c语言)。例如c++版本的math.h为cmath.

问题2:using namespace std 是什么?

namespace是指标识符的各种可见范围。命名空间用关键字namespace 来定义。命名空间是C++的一种机制,用来把单个标识符下的大量有逻辑联系的程序实体组合到一起。此标识符作为此组群的名字。

问题3:cout 、endl 是什么?

cout是c++中的标准输出流,endl是输出换行并刷新缓冲区。

1.2 namespace 【命名空间】

C++中自定义命名空间(namespace)及其使用的三种方法_自定义namespace-CSDN博客

由于namespace的概念,使用C++标准程序库的任何标识符时,可 以有三种选择:

1)直接指定标识符。例如std::ostream而不是ostream。完整语句如 下:

std::cout	<<	std::hex	<<	3.4	<<	std::endl;	

2)使用using关键字。

using	std::cout;	
using	std::endl;	
using	std::cin;

3)最方便的就是使用using namespace std;

4.命名空间使用语法

  1. 创建一个命名空间:
namespace A{int a = 10;
}
namespace B{int a = 20;
}
void test(){cout << "A::a : " << A::a << endl;cout << "B::a : " << B::a << endl;
}

        2.命名空间只能全局范围内定义(以下错误写法)

void test(){namespace A{int a = 10;}namespace B{int a = 20;}cout << "A::a : " << A::a << endl;cout << "B::a : " << B::a << endl;
}

        3.命名空间可以嵌套命名

namespace A{int a = 10;namespace B{int a = 20;}
}
void test(){cout << "A::a : " << A::a << endl;cout << "A::B::a : " << A::B::a << endl;
}

        4.命名空间是开放的,可以随时加入新的成员

namespace A{int a = 10;
}namespace A{void func(){cout << "hello namespace!" << endl;}
}

        5.声明和实现可以分离

#pragma oncenamespace MySpace{void func1();void func2(int param);
}void MySpace::func1(){cout << "MySpace::func1" << endl;
}
void MySpace::func2(int param){cout << "MySpace::func2 : " << param << endl;
}

        6.命名空间起别名

namespace veryLongName{int a = 10;void func(){ cout << "hello namespace" << endl; }
}void test(){namespace shortName = veryLongName;cout << "veryLongName::a : " << shortName::a << endl;veryLongName::func();shortName::func();
}

2.C++对C的扩展

2.1 ::作用域运算符

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;//定义一个命名空间
namespace spaccA {int g_a = 10;
}namespace spaceB {int a = 20;namespace spaceC {struct teacher{int id;char name[64];};}namespace spaceD {struct teacher{int id;char name[64];};}using namespace spaceC;}int main(void)
{//using spaccA::g_a;using namespace spaccA;int a = 10;cout << g_a << endl;//spaceB::spaceC::teacher t1;//using spaceB::spaceC::teacher;//teacher t1;//using namespace spaceB::spaceC;//spaceB::spaceC::teacher t1;using namespace spaceB;teacher t1;t1.id = 10;//spaceB::spaceD::teacher t2;//t2.id = 20;return 0;
}

2.2 "实用性“增强

c语言一定要在使用之前先定义

c++可以在使用的时候进行定义

//C语⾔中的变量都必须在作⽤域开始的位置定义!!
//C++中更强调语⾔的“实⽤性”,所有的变量都可以在需要使⽤时再定义。
#include<iostream>
using namespace std;
int main() {int i = 0;cout << "i=" << i << endl;int k = 4;cout << "k=" << k << endl;return 0;
}

2.3 变量检测增强

c语言允许定义多个同名的变量

c++不能定义多个同名变量,即使作用域不同

/*在C语⾔中,重复定义多个同名的全局变量是合法的在C++中,不允许定义多个同名的全局变量C语⾔中多个同名的全局变量最终会被链接到全局数据区的同⼀个地址空间上int	g_var;int	g_var	=	1;C++直接拒绝这种⼆义性的做法。
*/
#include<iostream>
int	g_var;
int	g_var = 1;
int	main(int argc, char* argv[])
{printf("g_var	=	%d\n", g_var);return 0;
}

2.4 C++中所有变量和函数都必须有类型

C++中所有的变量和函数都必须有类型

C语⾔中的默认类型在C++中是不合法的

函数f的返回值是什么类型,参数⼜是什么类型?

函数g可以接受多少个参数?

//i没有写类型,可以是任意类型
int fun1(i){printf("%d\n", i);return 0;
}
//i没有写类型,可以是任意类型
int fun2(i){printf("%s\n", i);return 0;
}
//没有写参数,代表可以传任何类型的实参
int fun3(){ printf("fun33333333333333333\n");return 0;
}//C语言,如果函数没有参数,建议写void,代表没有参数
int fun4(void){printf("fun4444444444444\n");return 0;
}g(){return 10;
}int main(){fun1(10);fun2("abc");fun3(1, 2, "abc");printf("g = %d\n", g());return 0;
}
  1. 在C语言中,int fun() 表示返回值为int,接受任意参数的函数,int fun(void) 表示返回值为int的无参函数。
  2. 在C++ 中,int fun() 和int fun(void) 具有相同的意义,都表示返回值为int的无参函数。

2.5 更严格的类型转换

在C++,不同类型的变量一般是不能直接赋值的,需要相应的强转。

以上c代码c编译器编译可通过,c++编译器无法编译通过。

typedef enum COLOR{ GREEN, RED, YELLOW } color;
int main(){color mycolor = GREEN;mycolor = 10;printf("mycolor:%d\n", mycolor);char* p = malloc(10);return EXIT_SUCCESS;
}

2.6 struct类型加强

  1. c中定义结构体变量需要加上struct关键字,c++不需要。
  2. c中的结构体只能定义成员变量,不能定义成员函数。c++即可以定义成员变量,也可以定义成员函数。
//1. 结构体中即可以定义成员变量,也可以定义成员函数
struct Student{string mName;int mAge;void setName(string name){ mName = name; }void setAge(int age){ mAge = age; }void showStudent(){cout << "Name:" << mName << " Age:" << mAge << endl;}
};//2. c++中定义结构体变量不需要加struct关键字
void test01(){Student student;student.setName("John");student.setAge(20);student.showStudent();
}

2.7 对函数返回参数个数的要求

C传递参数大于实际定义的参数,只会报警告,C++传递参数大于实际定义的参数会报错

2.8 新增的bool类的关键字

bool b=100;//无论将修改为多少,sizeof(b)永远为1

#include	<iostream>
using namespace	std;
int	main(int	argc, char* argv[])
{int	a;bool	b = true;printf("b	=	%d,	sizeof(b)	=	%d\n", b, sizeof(b));//1   1b = 4;a = b;printf("a	=	%d,	b	=	%d\n", a, b);//1   1b = -4;a = b;printf("a	=	%d,	b	=	%d\n", a, b);//1     1a = 10;b = a;printf("a	=	%d,	b	=	%d\n", a, b);//10   1b = 0;printf("b	=	%d\n", b);//0return 0;
}

2.9 三目运算符功能增强

  1. c语言三目运算表达式返回值为数据值,为右值,不能赋值。
	int a = 10;int b = 20;printf("ret:%d\n", a > b ? a : b);//思考一个问题,(a > b ? a : b) 三目运算表达式返回的是什么?//(a > b ? a : b) = 100;//错误//返回的是右值
  1. c++语言三目运算表达式返回值为变量本身(引用),为左值,可以赋值。
int a = 10;int b = 20;printf("ret:%d\n", a > b ? a : b);//思考一个问题,(a > b ? a : b) 三目运算表达式返回的是什么?cout << "b:" << b << endl;//20//返回的是左值,变量的引用(a > b ? a : b) = 100;//返回的是左值,变量的引用cout << "b:" << b << endl;//100

2.10 const增强

const单词字面意思为常数,不变的。它是c/c++中的一个关键字,是一个限定符,它用来限定一个变量不允许改变,它将一个对象转换成一个常量。

1.c语言中的const

们c中的const理解为”一个不能改变的普通变量”,也就是认为const应该是一个只读变量,既然是变量那么就会给const分配内存,并且在c中const是一个全局只读变量,c语言中const修饰的只读变量是外部连接的。

2.c++中的const

在c++中,一个const不必创建内存空间,而在c中,一个const总是需要一块内存空间。在c++中,是否为const常量分配内存空间依赖于如何使用。一般说来,如果一个const仅仅用来把一个名字用一个值代替(就像使用#define一样),那么该存储局空间就不必创建。

3.C/C++中const异同总结

//const	定义常量--->	const	意味只读
const int	a;	
int const	b;	
//第⼀个第⼆个意思⼀样 代表⼀个常整形数
const int	*c;	
//第三个	c是⼀个指向常整形数的指针(所指向的内存数据不能被修改,但是本⾝可以修改)
int	*	const	d;	
//第四个	d	常指针(指针变量不能被修改,但是它所指向内存空间可以被修改)
const int	*	const	e	;	
//第五个	e⼀个指向常整形的常指针(指针和它所指向的内存空间,均不能被修改)

4.const 和 #define 的相同

#include	<iostream>		
//#define	N	10	
int	main()	
{	const int	a	=	1;			const int	b	=	2;			int	array[a	+	b]	=	{0};	int	i	=	0;							for(i	=	0;	i	<	(a+b);	i++)	{																												printf("array[%d]	=	%d\n",	i,	array[i]);	}																																												return 0;																				
}

C++中的const修饰的,是一个真正的常量,而不是C中变量(只读)。在 const修饰的常量编译期间,就已经确定下来了

5.const 和 #define 的区别

#include	<iostream>
void	fun1()	
{	#define	a	10const int	b	=	20;	
}	
void	fun2()	
{	printf("a	=	%d\n",	a);	//printf("b	=	%d\n",	b);
}	
int	main()	
{	fun1();	fun2();	return 0;	
}

  1. const有类型,可进行编译器类型安全检查。#define无类型,不可进行类型检查.
  2. const有作用域,而#define不重视作用域,默认定义处到文件结尾.如果定义在指定作用域下有效的常量,那么#define就不能用。

辨析;
 

#include	<stdio.h>
int	main()
{const int	a = 10;//将a的地址传递给pint* p = (int*)&a;printf("a===>%d\n", a);//10*p = 11;printf("a===>%d\n", a);//10return 0;
}
#include	<iostream>		
//#define	N	10	
int	main()
{const int	a = 1;const int	b = 2;int	array[a + b] = { 0 };int	i = 0;for (i = 0; i < (a + b); i++){printf("array[%d]	=	%d\n", i, array[i]);//0 0 0}return 0;
}
#include	<iostream>
void	fun1()
{
#define	a	10const int	b = 20;
}
void	fun2()
{printf("a	=	%d\n", a);//10//printf("b	=	%d\n",	b);
}
int	main()
{fun1();fun2();return 0;
}

2.11 真正的枚举

c 语言中枚举本质就是整型,枚举变量可以用任意整型赋值。而 c++中枚举 变量, 只能用被枚举出来的元素初始化。

#include<iostream>
using namespace	std;	
enum season	{SPR,SUM,AUT,WIN};	
int	main()	
{	enum	season	s	=	SPR;	//s	=	0;	//	error,	但是C语⾔可以通过s	=	SUM;	cout	<<	"s	=	"	<<	s	<<endl;//1return 0;	
}

3 引⽤(reference)

3.1 引用基本用法

引用是c++对c的重要扩充。在c/c++中指针的作用基本都是一样的,但是c++增加了另外一种给函数传递地址的途径,这就是按引用传递(pass-by-reference),它也存在于其他一些编程语言中,并不是c++的发明。

  1. 变量名实质上是一段连续内存空间的别名,是一个标号(门牌号)
  2. 程序中通过变量来申请并命名内存空间
  3. 通过变量的名字可以使用存储空间

对一段连续的内存空间只能取一个别名吗?

c++中新增了引用的概念,引用可以作为一个已定义变量的别名。

基本语法

Type & ref=val;
int & ref=&a;//表示ref是a的别名
#include<iostream>
using namespace std;
int main() {int a = 10;int& b = a;//int* ba = 11;{int* p = &a;*p = 12;cout << a << endl;//12}b = 14;cout << a <<"" << b << endl;//14 14
}

注意事项:

  1. &在此不是求地址运算,而是起标识作用。
  2. 类型标识符是指目标变量的类型
  1. 必须在声明引用变量时进行初始化。
  2. 引用初始化之后不能改变。
  3. 不能有NULL引用。必须确保引用是和一块合法的存储单元关联。
  4. 可以建立对数组的引用。
//1. 认识引用
void test01(){int a = 10;//给变量a取一个别名bint& b = a;cout << "a:" << a << endl;cout << "b:" << b << endl;cout << "------------" << endl;//操作b就相当于操作a本身b = 100;cout << "a:" << a << endl;cout << "b:" << b << endl;cout << "------------" << endl;//一个变量可以有n个别名int& c = a;//给c取了一个名为”c”的别名c = 200;cout << "a:" << a << endl;cout << "b:" << b << endl;cout << "c:" << c << endl;cout << "------------" << endl;//a,b,c的地址都是相同的cout << "a:" << &a << endl;cout << "b:" << &b << endl;cout << "c:" << &c << endl;
}
//2. 使用引用注意事项
void test02(){//1) 引用必须初始化//int& ref; //报错:必须初始化引用//2) 引用一旦初始化,不能改变引用int a = 10;int b = 20;int& ref = a;ref = b; //不能改变引用//3) 不能对数组建立引用int arr[10];//int& ref3[10] = arr;
}

3.2 注意点 

1.一个变量可以有n个别名

2.操作别名等于操作原数

3.别名和操作数的地址是一样的

4.引用必须初始化

5.一旦初始化,不能进行修改

6.不能对数组建立引用

3.3 建立对数组的引用

方法一:

	typedef int ArrRef[10];int arr[10];ArrRef& aRef = arr;for (int i = 0; i < 10;i ++){aRef[i] = i+1;}for (int i = 0; i < 10;i++){cout << arr[i] << " ";}cout << endl;

方法二:

	int(&f)[10] = arr;for (int i = 0; i < 10; i++){f[i] = i+10;}for (int i = 0; i < 10; i++){cout << arr[i] << " ";}cout << endl;

3.4 函数中的引用

当引用被用作函数参数的时,在函数内对任何引用的修改,将对还函数外的参数产生改变

//值传递
void ValueSwap(int m,int n){int temp = m;m = n;n = temp;
}
//地址传递
void PointerSwap(int* m,int* n){int temp = *m;*m = *n;*n = temp;
}
//引用传递
void ReferenceSwap(int& m,int& n){int temp = m;m = n;n = temp;
}
void test(){int a = 10;int b = 20;//值传递ValueSwap(a, b);cout << "a:" << a << " b:" << b << endl;//地址传递PointerSwap(&a, &b);cout << "a:" << a << " b:" << b << endl;//引用传递ReferenceSwap(a, b);cout << "a:" << a << " b:" << b << endl;
}

通过引用参数产生的效果同按地址传递是一样的。引用的语法更清楚简单:  

  1. 函数调用时传递的实参不必加“&”符
  2. 在被调函数中不必在参数前加“*”符

引用作为其它变量的别名而存在,因此在一些场合可以代替指针。C++主张用引用传递取代地址传递的方式,因为引用语法容易且不易出错。

#include	<iostream>
using namespace	std;
int	getA1()
{int	a;a = 10;return	a;
}
int& getA2()
{int	a;a = 10;return	a;
}
int	main(void)
{int	a1 = 0;int	a2 = 0;//值拷⻉a1 = getA1();//将⼀个引⽤赋给⼀个变量,会有拷⻉动作//理解: 编译器类似做了如下隐藏操作,a2	=	*(getA2())a2 = getA2();//将⼀个引⽤赋给另⼀个引⽤作为初始值,由于是栈的引⽤,内存⾮法int& a3 = getA2();cout << "a1	=	" << a1 << endl;cout << "a2	=	" << a2 << endl;cout << "a3	=	" << a3 << endl;return 0;
}
#include	<iostream>
using namespace	std;
//函数当左值
//返回变量的值
int	func1()
{static int	a1 = 10;return	a1;
}
//返回变量本⾝	,	
int& func2()
{static int	a2 = 10;return	a2;
}
int	main(void)
{//函数当右值int	c1 = func1();cout << "c1	=	" << c1 << endl;int	c2 = func2();	//函数返回值是⼀个引⽤,并且当右值cout << "c2	=	" << c2 << endl;//函数当左值//func1()	=	100;				//errorfunc2() = 100;						//函数返回值是⼀个引⽤,并且当左值c2 = func2();cout << "c2	=	" << c2 << endl;return 0;
}

注意点:

  1. 不能返回局部变量的引用。
  2. 函数当左值,必须返回引用。【因为引用定义的函数,返回的是别名】

3.5 引用的本质:指针常量.(int* const ref)

引用的本质在c++内部实现是一个指针常量.

Type& ref = val; // Type* const ref = &val;

c++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同,只是这个过程是编译器内部实现,用户不可见。

//发现是引用,转换为 int* const ref = &a;
void testFunc(int& ref){ref = 100; // ref是引用,转换为*ref = 100
}
int main(){int a = 10;int& aRef = a; //自动转换为 int* const aRef = &a;这也能说明引用为什么必须初始化aRef = 20; //内部发现aRef是引用,自动帮我们转换为: *aRef = 20;cout << "a:" << a << endl;cout << "aRef:" << aRef << endl;testFunc(a);return EXIT_SUCCESS;
}

3.6 指针引用

对于c++中的定义那个,语法清晰多了。函数参数变成指针的引用,用不着取得指针的地址。

struct Teacher{int mAge;
};
//指针间接修改teacher的年龄
void AllocateAndInitByPointer(Teacher** teacher){*teacher = (Teacher*)malloc(sizeof(Teacher));(*teacher)->mAge = 200;  
}
//引用修改teacher年龄
void AllocateAndInitByReference(Teacher*& teacher){teacher->mAge = 300;
}
void test(){//创建TeacherTeacher* teacher = NULL;//指针间接赋值AllocateAndInitByPointer(&teacher);cout << "AllocateAndInitByPointer:" << teacher->mAge << endl;//引用赋值,将teacher本身传到ChangeAgeByReference函数中AllocateAndInitByReference(teacher);cout << "AllocateAndInitByReference:" << teacher->mAge << endl;free(teacher);
}
#include	<iostream>
using namespace	std;
struct	Teacher
{char	name[64];int	age;
};
//在被调⽤函数 获取资源
int	getTeacher(Teacher * *p)
{Teacher* tmp = NULL;if (p == NULL){return	-1;}tmp = (Teacher*)malloc(sizeof(Teacher));if (tmp == NULL){return	-2;}tmp->age = 33;//	p是实参的地址		*实参的地址 去间接的修改实参的值*p = tmp;return 0;
}
//指针的引⽤ 做函数参数
int	getTeacher2(Teacher*& myp)
{//给myp赋值 相当于给main函数中的pT1赋值myp = (Teacher*)malloc(sizeof(Teacher));if (myp == NULL){return	-1;}myp->age = 36;return 0;
}
void	FreeTeacher(Teacher* pT1)
{if (pT1 == NULL){return;}free(pT1);
}
int	main(void)
{Teacher* pT1 = NULL;//1	c语⾔中的⼆级指针getTeacher(&pT1);cout << "age:" << pT1->age << endl;FreeTeacher(pT1);//2	c++中的引⽤ (指针的引⽤)//引⽤的本质 间接赋值后2个条件 让c++编译器帮我们程序员做了。getTeacher2(pT1);cout << "age:" << pT1->age << endl;FreeTeacher(pT1);return 0;
}

3.7 常量引用(const)

常量引用的定义格式:

const Type& ref = val;

注意:

  1. 如果想对一个常量进行引用, 必须是一个const引用。
  2. const修饰的引用,不能修改。

void test01(){int a = 100;const int& aRef = a; //此时aRef就是a//aRef = 200; 不能通过aRef的值a = 120; //OKcout << "a:" << a << endl;//120cout << "aRef:" << aRef << endl;//120
}
void test02(){//不能把一个字面量赋给引用//int& ref = 100;//但是可以把一个字面量赋给常引用//因为const int的级别比int高const int& ref = 100; //int temp = 200; const int& ret = temp;
}

    [const引用使用场景]

    常量引用主要用在函数的形参,尤其是类的拷贝/复制构造函数。

将函数的形参定义为常量引用的好处:

  • 引用不产生新的变量,减少形参与实参传递时的开销。
  • 由于引用可能导致实参随形参改变而改变,将其定义为常量引用可以消除这种副作用。

    如果希望实参随着形参的改变而改变,那么使用一般的引用,如果不希望实参随着形参改变,那么使用常引用。

//const int& param防止函数中意外修改数据
void ShowVal(const int& param){cout << "param:" << param << endl;
}

3.8 例子

C++引用10分钟入门教程

#include	<iostream>
using namespace	std;
int	main(void)
{int	a = 10;	//c编译器分配4个字节内存,	a内存空间的别名int& b = a;		//b就是a的别名-->const * int b=aa = 11;	//直接赋值{int* p = &a;*p = 12;cout << a << endl;//12}b = 14;cout << "a	=	" << a << ",	b	=	" << b << endl;//14 14return 0;
}

结论:可以通过普通参数修改引用,但是不能通过引用修改参数 

#include	<iostream>
using namespace	std;
int main() {int a = 20;int&  ref = a;ref = 30;cout << ref << a << endl;//30  30int b = 40;const int& ref2 = b;b = 100;cout << ref2 << b << endl;//100 100int& rref = ref;rref = 200;cout << rref << ref << a << endl;//200 200 200
}

作业:

1.简述C++中命名空间的作用。

namespace AAA{
    int a;

using AAA::a;
AAA::a;
using namespace AAA;

2. 定义两个命名空间A 和 B 分别在A中和B中定义变量value

#include<iostream>using namespace std;namespace A {int a = 10;
}
namespace B {int b = 20;
}
int main() {using namespace A;using namespace B;cout << A::a << endl;cout << B::b << endl;}

3. C语言的三目运算符 ? : , 可以当左值么? C++的是否可以? 为什么?

c语言的三目运算符不可以当左值,因为返回的是一个常量。

c++的三目运算符可以做左值

4. 下面哪条语句是错误的?为什么?

(1 < 2? a: b) = 100;//正确,因为结果是一个变量,可以被赋值
   
(1 < 2? 10: 20) = 100//错误,因为结果是一个常量,常量不能被常量赋值

5. const int a; 在C++编译器中是否需要初始化,为什么?
 

在c++中,一旦声明一个const变量,则在声明的过程中一定要对起进行初始化

6.temp

int main() {int a = 10;int* p = (int*)&a;//*p:实际上修改的是temp的值*p = 20;cout << a << endl;//20cout << *p << endl;//20}

6. 简述引用的特点?

1.引用本身不占用内存空间,与被引用对象共用内存

2.引用定义时,必须初始化

3.引用的类型必须与被引用对象的类型保持一致 比如:int a; 引用必须使用int&

4.引用只能引用一个对象,一个对象可以被多次引用。

7.判断

int main() {int a = 20;const int& re_a = a;re_a = 30;//错误,不能直接修改const变量}

 4.inline内联函数

https://www.cnblogs.com/chengxuyuancc/archive/2013/04/04/2999844.html

4.1 内联函数的引出

c++从c中继承的一个重要特征就是效率。假如c++的效率明显低于c的效率,那么就会有很大的一批程序员不去使用c++了。

4.2  预处理宏的缺陷

宏函数是预处理器进行的

内联的编译器处理的

预处理器宏存在问题的关键是我们可能认为预处理器的行为和编译器的行为是一样的。当然也是由于宏函数调用和函数调用在外表看起来是一样的,因为也容易被混淆。但是其中也会有一些微妙的问题出现:

问题一:

#define ADD(x,y) x+y
inline int Add(int x,int y){return x + y;
}
void test(){int ret1 = ADD(10, 20) * 10; //希望的结果是300int ret2 = Add(10, 20) * 10; //希望结果也是300cout << "ret1:" << ret1 << endl; //210cout << "ret2:" << ret2 << endl; //300
}

问题二:

#define COMPARE(x,y) ((x) < (y) ? (x) : (y))
int Compare(int x,int y){return x < y ? x : y;
}
void test02(){int a = 1;int b = 3;//cout << "COMPARE(++a, b):" << COMPARE(++a, b) << endl; // 3cout << "Compare(int x,int y):" << Compare(++a, b) << endl; //2
}

4.3 内联函数基本概念:空间换时间

在c++中,预定义宏的概念是用内联函数来实现的,而内联函数本身也是一个真正的函数。内联函数具有普通函数的所有行为。唯一不同之处在于内联函数会在适当的地方像预定义宏一样展开,所以不需要函数调用的开销。因此应该不使用宏,使用内联函数。

注意必须函数体和声明结合在一起,否则编译器将它作为普通函数来对待。

inline void func(int a);
inline int func(int a) {return a;
}

内联函数的确占用空间,但是内联函数相对于普通函数的优势只是省去了函数调用时候的压栈,跳转,返回的开销。我们可以理解为内联函数是以空间换时间

4.4 类内部的内联函数

为了定义内联函数,通常必须在函数定义前面放一个inline关键字。但是在类内部定义内联函数时并不是必须的。任何在类内部定义的函数自动成为内联函数。

class Person{
public:Person(){ cout << "构造函数!" << endl; }void PrintPerson(){ cout << "输出Person!" << endl; }
}

4.5 内联函数和编译器

4.6 注意点

  • 不能存在任何形式的循环语句
  • 不能存在过多的条件判断语句
  • 函数体不能过于庞大
  • 不能对函数进行取址操作

内联仅仅只是给编译器一个建议,编译器不一定会接受这种建议,如果你没有将函数声明为内联函数,那么编译器也可能将此函数做内联编译。一个好的编译器将会内联小的、简单的函数。

4.7 内联函数 VS 宏函数

4.8 总结

5. 函数的默认参数和占位函数

5.1 默认参数

c++在声明函数原型的时可为一个或者多个参数指定默认(缺省)的参数值,当函数调用的时候如果没有指定这个值,编译器会自动用默认值代替。

void TestFunc01(int a = 10, int b = 20){cout << "a + b  = " << a + b << endl;
}
//注意点:
//1. 形参b设置默认参数值,那么后面位置的形参c也需要设置默认参数
void TestFunc02(int a,int b = 10,int c = 10){}
//2. 如果函数声明和函数定义分开,函数声明设置了默认参数,函数定义不能再设置默认参数
void TestFunc03(int a = 0,int b = 0);
void TestFunc03(int a, int b){}int main(){//1.如果没有传参数,那么使用默认参数TestFunc01();//2. 如果传一个参数,那么第二个参数使用默认参数TestFunc01(100);//3. 如果传入两个参数,那么两个参数都使用我们传入的参数TestFunc01(100, 200);return EXIT_SUCCESS;
}

注意点:

5.2  函数的占位参数

c++在声明函数时,可以设置占位参数。占位参数只有参数类型声明,而没有参数名声明。一般情况下,在函数体内部无法使用占位参数。【占位符也是参数,必须传参数】

void TestFunc01(int a,int b,int){//函数内部无法使用占位参数cout << "a + b = " << a + b << endl;
}
//占位参数也可以设置默认值
void TestFunc02(int a, int b, int = 20){//函数内部依旧无法使用占位参数cout << "a + b = " << a + b << endl;
}
int main(){//错误调用,占位参数也是参数,必须传参数//TestFunc01(10,20); //正确调用TestFunc01(10,20,30);//正确调用TestFunc02(10,20);//正确调用TestFunc02(10, 20, 30);return EXIT_SUCCESS;
}

6. 函数重载(overload)

6.1 函数重载概述

    能使名字方便使用,是任何程序设计语言的一个重要特征!

在传统c语言中,函数名必须是唯一的,程序中不允许出现同名的函数。在c++中是允许出现同名的函数,这种现象称为函数重载。

函数重载的目的就是为了方便的使用函数名。

6.2 函数重载基本语法

实现函数重载的条件:

  1. 同一个作用域
  2. 参数个数不同
  3. 参数类型不同
  4. 参数顺序不同
  5. 返回值并不是构成函数重载的条件
//1. 函数重载条件
namespace A{void MyFunc(){ cout << "无参数!" << endl; }void MyFunc(int a){ cout << "a: " << a << endl; }void MyFunc(string b){ cout << "b: " << b << endl; }void MyFunc(int a, string b){ cout << "a: " << a << " b:" << b << endl;}void MyFunc(string b, int a){cout << "a: " << a << " b:" << b << endl;}
}
//2.返回值不作为函数重载依据
namespace B{void MyFunc(string b, int a){}//int MyFunc(string b, int a){} //无法重载仅按返回值区分的函数
}

注意: 函数重载和默认参数一起使用,需要额外注意二义性问题的产生。

为什么函数返回值不作为重载条件呢?

调用准则

#include	<iostream>
using namespace	std;
void	print(double	a) {cout << a << endl;
}
void print(int	a) {cout << a << endl;
}
int	main()
{print(1);	//	print(int)print(1.1);	//	print(double)print('a');	//	print(int)print(1.11f);	//	print(double)return 0;
}

编译器调用重载函数的准则:

6.3 重载底层实现(name mangling)

6.4 函数重载与函数默认参数

6.5 函数重载和函数指针

函数指针基本语法

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;int func(int a, int b)
{cout << "func(int, int)" << endl;return 0;
}int func(int a, int b, int c)
{cout << "func(int, int,int )" << endl;return 0;
}//1 . 定义一种函数类型
typedef int(MY_FUNC)(int, int);//2 顶一个指向之中函数类型的指针类型
typedef int(*MY_FUNC_P)(int, int);int main(void)
{//1.MY_FUNC *fp = NULL;fp = func;fp(10, 20);//2.MY_FUNC_P fp1 = NULL;fp1 = func;fp1(10, 20);//3. int(*fp3)(int, int) = NULL;fp3 = func;fp3(10, 20);func(10, 20);func(10, 20, 30);fp3 = func; //fp3 ---> func(int,int)//实际上在给函数指针赋值的时候,是会发生函数重载匹配的//在调用函数指针的时候,所调用的函数就已经固定了。int(*fp4)(int, int, int) = NULL;fp4 = func; //fp4 ---> func(int,int,int)fp3(10, 30);//func(int,int)fp3(10, 20);fp4(10, 30, 30);return 0;
}

6.6 总结

7.类和对象

7.1 类和对象的基本概念

C和C++中struct区别

  1. c语言struct只有变量
  2. c++语言struct 既有变量,也有函数

访问控制权限

一个类类的内部,是默认private

我们编写程序的目的是为了解决现实中的问题,而这些问题的构成都是由各种事物组成,我们在计算机中要解决这种问题,首先要做就是要将这个问题的参与者:事和物抽象到计算机程序中,也就是用程序语言表示现实的事物。

//封装两层含义
//1. 属性和行为合成一个整体
//2. 访问控制,现实事物本身有些属性和行为是不对外开放
class Person{
//人具有的行为(函数)
public:void Dese(){ cout << "我有钱,年轻,个子又高,就爱嘚瑟!" << endl;}
//人的属性(变量)
public:int mTall; //多高,可以让外人知道
protected:int mMoney; // 有多少钱,只能儿子孙子知道
private:int mAge; //年龄,不想让外人知道
};int main(){Person p;p.mTall = 220;//p.mMoney 保护成员外部无法访问//p.mAge 私有成员外部无法访问p.Dese();return EXIT_SUCCESS;
}

sruct和class的区别

class A{int mAge;
};
struct B{int mAge;
};void test(){A a;B b;//a.mAge; //无法访问私有成员b.mAge; //可正常外部访问
}
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;struct Hero
{char name[64];int sex;
};void printHero(struct Hero& h)
{cout << "Hero" << endl;cout << "name = " << h.name << endl;cout << "sex = " << h.sex << endl;
}class AdvHero
{
public://访问控制权限char name[64];int sex;void printHero(){cout << "advHero" << endl;cout << "name = " << name << endl;cout << "sex = " << sex << endl;}
};class Animal
{//{}以内 叫类的内部, 以外叫类的外部
public:char kind[64];char color[64];//在public下面定义成员变量和函数 是能够在类的内部和外部都可以访问的。void printAnimal(){cout << "kind = " << kind << endl;cout << "color = " << color << endl;}void write(){cout << kind << "开始鞋子了" << endl;}void run(){cout << kind << "跑起来了" << endl;}//
private://在private下面定义的成员变量和方法只能够在类的内部访问};int main(void)
{Hero h;strcpy(h.name, "gailun");h.sex = 1;printHero(h);AdvHero advH;strcpy(advH.name, "ChunBro");advH.sex = 1;advH.printHero();cout << "-----------" << endl;Animal dog;strcpy(dog.kind, "dog");strcpy(dog.color, "yellow");Animal sheep;strcpy(sheep.kind, "sheep");strcpy(sheep.color, "white");dog.write();sheep.run();return 0;
}

将成员变量设置为private

class AccessLevels{
public://对只读属性进行只读访问int getReadOnly(){ return readOnly; }//对读写属性进行读写访问void setReadWrite(int val){ readWrite = val; }int getReadWrite(){ return readWrite; }//对只写属性进行只写访问void setWriteOnly(int val){ writeOnly = val; }
private:int readOnly; //对外只读访问int noAccess; //外部不可访问int readWrite; //读写访问int writeOnly; //只写访问
};

7.2 用class去封装带行为的类

class 封装的本质,在于将数据和行为,绑定在一起然后能过对象来完成操 作。

#include	<iostream>
using namespace	std;
class	Date
{
public:void	init(Date & d);void	print(Date& d);bool	isLeapYear(Date& d);
private:int	year;int	month;int	day;
};
void	Date::init(Date& d)
{cout << "year,month,day:" << endl;cin >> d.year >> d.month >> d.day;
}
void	Date::print(Date& d)
{cout << "year	month	day" << endl;cout << d.year << ":" << d.month << ":" << d.day << endl;
}
bool	Date::isLeapYear(Date& d)
{if ((d.year % 4 == 0 && d.year % 100 != 0) || d.year % 400 == 0)return true;elsereturn false;
}
int	main()
{Date	d;d.init(d);d.print(d);if (d.isLeapYear(d))cout << "leap	year" << endl;elsecout << "not	leap	year" << endl;return 0;
}

7.3 类的封装

一般类中的属性是private

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;struct Date
{int year;int month;int day;
};void init_date(struct Date & d)
{cout << "year, month, day" << endl;cin >> d.year;cin >> d.month;cin >> d.day;
}//打印data的接口
void print_date(struct Date &d)
{cout << d.year << "年" << d.month << "月" << d.day << "日" << endl;
}bool is_leap_year(struct Date &d)
{if (((d.year % 4 == 0) && (d.year % 100 != 0)) || (d.year % 400 == 0)) {return true;}return false;
}class MyDate
{
public://成员方法 成员函数void init_date(){cout << "year, month, day" << endl;cin >> year;cin >> month;cin >> day;}//打印data的接口void print_date(){cout << year << "年" << month << "月" << day << "日" << endl;}bool is_leap_year(){if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {return true;}return false;}int get_year(){return year;}void set_year(int new_year){year = new_year;}protected://保护控制权限。在类的继承中跟private有区别,在单个类中,跟private是一抹一样。
private:int year;int month;int day;
};//一个类类的内部,默认的访问控制权限是private
class Hero
{int year;
};//一个结构体默认的访问控制权限的是public
struct Hero2
{int year;void print(){}
};int main(void)
{
#if 0Date d1;init_date(d1);print_date(d1);if (is_leap_year(d1) == true) {cout << "是闰年 " << endl;}else {cout << "不是闰年 " << endl;}
#endifMyDate my_date;my_date.init_date();my_date.print_date();if (my_date.is_leap_year() == true){cout << "是闰年 " << endl;}else {cout << "不是闰年 " << endl;}//getter,settercout << my_date.get_year() << endl;my_date.set_year(2000);cout << my_date.get_year() << endl;Hero h;//h.year = 1000;Hero2 h2;h2.year = 100;return 0;
}

7.4 ⾯向对象编程

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;//面向对象
class Dog
{
public:void eat(char *food){cout << name << "吃" << food << endl;}char name[64];
};//面向过程
void eat(class Dog &dog, char *food)
{cout << dog.name << "吃" << food << endl;
}int main(void)
{Dog dog;strcpy(dog.name, "狗");eat(dog, "翔");dog.eat("翔");return 0;
}

 求圆的面积和周长

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;//圆的周长
double getCircleGirth(double r)
{return 2 * 3.14 * r;
}//源的面积
double getCircleArea(double r)
{return 3.14 * r * r;
}//用面向对象实现//圆类
class Circle
{
public:void setR(double r){m_r = r;}double getR(){return m_r;}double getGirth(){return 2 * 3.14 * m_r;}double getArea(){return m_r * m_r * 3.14;}private:double m_r; //圆的私有成员 半径
};class Circle2
{
public:void setR(double r){m_r = r;}double getR(){return m_r;}double getArea(){m_area = m_r * m_r * 3.14;return m_area;}double getGirth(){m_girth = m_r * 2 * 3.14;return m_girth;}private:double m_r;double m_girth; //周长double m_area;//面积
};int main(void)
{double r = 10; //圆的半径double g = 0;double a = 0;g = getCircleGirth(r);a = getCircleArea(r);cout << "圆的半径是" << r << endl;cout << "圆的周长是" << g << endl;cout << "圆的面积是" << a << endl;cout << "------" << endl;Circle c;c.setR(10);cout << "圆的半径是" << c.getR() << endl;cout << "圆的周长是" << c.getGirth() << endl;cout << "圆的面积是" << c.getArea() << endl;cout << "------------" << endl;Circle2 c2;c2.setR(10);cout << "圆的半径是" << c2.getR() << endl;cout << "圆的周长是" << c2.getGirth() << endl;cout << "圆的面积是" << c2.getArea() << endl;return 0;
}

圆的周长和面积多文件编写

Circle.h

#pragma once#if 0
#ifndef __CIRCLE_H_
#define __CIRCLE_H_#endif
#endifclass Circle
{
public://设置半径:void setR(double r);//得到半径double getR();double getArea();double getGirth();private:double m_r;double m_area;double m_girth;
};

Circle.cpp

#include "Circle.h"//Circle::表示还在圆的内部
void Circle::setR(double r)
{m_r = r;
}double Circle::getR()
{return m_r;
}double Circle::getArea()
{m_area = m_r *m_r *3.14;return m_area;
}double Circle::getGirth()
{m_girth = m_r * 2 * 3.14;return m_girth;
}

mian.cpp

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>#include "Circle.h"using namespace std;int main(void)
{Circle c;c.setR(10);cout << "面积" << c.getArea() << endl;return 0;
}

判断两个立方体是否相等

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;//立方体类
class Cube
{
public:void setABC(int a, int b, int c){m_a = a;m_b = b;m_c = c;}int getArea(){return (m_a*m_b) * 2 + (m_a*m_c) * 2 + (m_b*m_c) * 2;}int getVolume(){return (m_a*m_b*m_c);}int getA(){return m_a;}int getB(){return m_b;}int getC(){return m_c;}//同类之间无私处bool judgeCube(Cube &another){if (m_a == another.m_a &&m_b == another.getB() &&m_c == another.getC()) {return true;}else {return false;}}
private:int m_a;int m_b;int m_c;
};//全局函数
bool judgeCube(Cube &c1, Cube &c2)
{if (c1.getA() == c2.getA() &&c1.getB() == c2.getB() &&c1.getC() == c2.getC()) {return true;}else {return false;}
}int main(void)
{Cube c1;c1.setABC(10, 20, 30);Cube c2;c2.setABC(10, 20, 30);cout << "c1 的体积是" << c1.getVolume() << endl;cout << "c1 的面积是" << c1.getArea() << endl;if (judgeCube(c1, c2) == true) {cout << "相等" << endl;}else {cout << "不相等" << endl;}cout << " ------ " << endl;if (c1.judgeCube(c2) == true) {cout << "相等" << endl;}else {cout << "不相等" << endl;}return 0;
}

判断点是否在圆的内部

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;//点类
class Point
{
public:void setXY(int x, int y){m_x = x;m_y = y;}int getX(){return m_x;}int getY(){return m_y;}
private:int m_x;int m_y;
};//圆类
class Circle
{
public:void setXY(int x, int y){x0 = x;y0 = y;}void setR(int r){m_r = r;}//提供一个判断点是否在圆内//true 在内部//false 在外部bool judgePoint(Point &p){int dd;dd = (p.getX() - x0)*(p.getX() - x0) + (p.getY() - y0)*(p.getY() - y0);if (dd > m_r*m_r) {return false;}else {return true;}}private:int x0;int y0;int m_r;
};int main(void)
{Circle c;c.setXY(2, 2);c.setR(4);Point p;p.setXY(8, 8);if (c.judgePoint(p) == true) {cout << "圆的内部" << endl;}else {cout << "圆的外部" << endl;}return 0;
}

判断两个圆是否相交

#include<iostream>
using namespace std;
class Point {
public:void setXY(int x, int y) {m_x = x;m_y = y;}//计算两个点之间的距离double pointDistance(Point& another) {int dis_x = m_x - another.m_x;int dis_y = m_y - another.m_y;//斜边double dis = sqrt(dis_x * dis_x + dis_y * dis_y);return dis;}private:int m_x;int m_y;
};
class Circle {
public:void setR(int r) {m_r = r;}void setXY(int x1, int y1) {p0.setXY(x1, y1);}//判断圆是否相交bool isConnection(Circle& another) {//两个圆的半径之和int r = m_r + another.m_r;//两个圆心之间的距离double dis = p0.pointDistance(another.p0);if (dis <= r) {			//相交return true;}else {return false;}}private:int m_r;Point p0;
};int main(void)
{Circle c1, c2;int x, y, r;cout << "请输入第一个圆的半径" << endl;cin >> r;c1.setR(r);cout << "请输入第一个圆的x" << endl;cin >> x;cout << "请输入第一个圆的y" << endl;cin >> y;c1.setXY(x, y);cout << "请输入第2个圆的半径" << endl;cin >> r;c2.setR(r);cout << "请输入第2个圆的x" << endl;cin >> x;cout << "请输入第2个圆的y" << endl;cin >> y;c2.setXY(x, y);if (c1.isConnection(c2) == true) {cout << "相交" << endl;}else {cout << "不想交" << endl;}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

AUTOSAR 面试知识回顾

如果答不上来&#xff0c;就讲当时做了什么 1. Ethernet基础: 硬件接口&#xff1a; ECU到PHY&#xff1a; data 是MII总线&#xff0c; 寄存器控制是SMI总线【MDCMDIO两根线, half duplex】PHY输出(100BASE-T1)&#xff1a; MDI总线&#xff0c;2 wire 【T1: twisted 1 pair …

【GO】LGTM_Grafana_gozero_配置trace(4)_代码实操及追踪

最近在尝试用 LGTM 来实现 Go 微服务的可观测性&#xff0c;就顺便整理一下文档。 Tempo 会分为 4 篇文章&#xff1a; Tempo 的架构官网测试实操跑通gin 框架发送 trace 数据到 tempogo-zero 微服务框架发送数据到 tempo 本文就是写一下如何在 go-zero 微服务框架里面配置 t…

golang入门笔记——pprof性能分析

文章目录 简介runtime/pprof的使用命令行交互网络服务性能分析pprof与性能测试结合压测工具go-wrk 简介 golang性能分析工具pprof的8个指标 1.性能分析的5个方面&#xff1a;CPU、内存、I/O、goroutine&#xff08;协程使用情况和泄漏检查&#xff09;、死锁检测以及数据竟态…

一篇文章成为递归大神:MySQL递归查询(with recursive)

理论原理 1、MySQL with Recursive是什么&#xff1f; MySQL with Recursive是一种基于递归思想的MySQL查询方式&#xff0c;可以实现对数据的递归查询和处理&#xff0c;返回符合条件的数据。在MySQL 8.0版本中&#xff0c;该功能被正式引入。 2、MySQL with Recursive有什么…

【kubernetes】使用virtual-kubelet扩展k8s

1 何为virtual-kubelet&#xff1f; kubelet是k8s的agent&#xff0c;负责监听Pod的调度情况&#xff0c;并运行Pod。而virtual-kubelet不是真实跑在宿主机上的&#xff0c;而是一个可以跑在任何地方的进程&#xff0c;该进程向k8s伪装成一个真实的Node&#xff0c;但是实际的…

ssm+vue的教室信息管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的教室信息管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&…

驱动开发--汇总

一&#xff0c;【驱动相关概念】 1&#xff0c;什么是驱动 能够驱使硬件实现特定功能的软件代码 根据驱动程序是否依赖于系统内核将驱动分为裸机驱动和系统驱动 2&#xff0c;逻辑驱动和系统驱动的区别 裸机驱动&#xff1a;编写的驱动代码中没有进行任何内核相关API的调用…

Selenium WebUI 自动化测试框架

框架结构 框架结构 框架基于 PO 模型进行设计&#xff0c;将页面元素与操作进行拆分&#xff0c;减少页面改动时的维护成本&#xff1b;同时使用 xsd 自定义 xml 标签&#xff0c;通过解析 xml 来驱动 selenium 进行执行&#xff0c;减少了一定的语言学习成本。 主要功能 基于…

关于地址存放的例题

unsigned int a 0x1234; unsigned char b *(unsigned char*)&a; 上面代码大端存储和小端存储的值分别是多少&#xff1f; 大端存储的是把高位地址存放在低位地址处&#xff0c;低位存放到高位。小端是高位存放在高位&#xff0c;低位在低位。因为a是整型&#xff0c;所…

C++ list容器的实现及讲解

所需要的基础知识 对C类的基本了解 默认构造函数 操作符重载 this指针 引用 模板等知识具有一定的了解&#xff0c;阅读该文章会很轻松。 链表节点 template<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T&…

K8S:Pod容器中的存储方式及PV、PVC

文章目录 Pod容器中的存储方式一&#xff0e;emptyDir存储卷1.emptyDir存储卷概念2.emptyDir存储卷示例 二.hostPath存储卷1.hostPath存储卷概念2.hostPath存储卷示例 三.nfs共享存储卷1.nfs共享存储卷示例 四.PV和PVC1.PV、PVC概念2.PVC 的使用逻辑及数据流向3.storageclass插…

MySQL面试题-索引的基本原理及相关面试题

先了解一下MySQL的结构 下面我们重点讲一下存储引擎 MySQL的数据库和存储数据的目录是一一对应的&#xff0c;这些数据库的文件就保存在磁盘中对应的目录里 下面我们来看一下对应的具体数据文件 .frm是表的结构&#xff0c;不管什么样的索引都会有 .ibd代表我们现在使用的存…

基于微信小程序的房屋租赁系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言运行环境说明用户微信小程序端的主要功能有&#xff1a;户主微信小程序端的主要功能有&#xff1a;管理员的主要功能有&#xff1a;具体实现截图详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考论文…

力扣刷题-链表-两两交换链表中的节点

24.两两交换链表中的节点 给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 解题思路 采用正常模拟的方法。 建议使用虚拟头结点&#xff0c;这样会方便很多&am…

仿制 Google Chrome 的恐龙小游戏

通过仿制 Google Chrome 的恐龙小游戏&#xff0c;我们可以掌握如下知识点&#xff1a; 灵活使用视口单位掌握绝对定位JavaScript 来操作 CSS 变量requestAnimationFrame 函数的使用无缝动画实现 页面结构 实现页面结构 通过上述的页面结构我们可以知道&#xff0c;此游戏中…

算法通关村第14关【白银】| 堆的经典问题

1.数组中的第k个最大元素 思路&#xff1a; 最直观的就是选择法&#xff0c;遍历一k次找到第k大的数之前使用快速排序的思想每次找出一个位置&#xff0c;会超时这里使用堆&#xff08;优先队列&#xff09;&#xff0c;找最大用小堆&#xff0c;找最小用大堆。 例如找第k大的…

【ArcGIS】土地利用变化分析详解(矢量篇)

土地利用变化分析详解-矢量篇 土地利用类型分类1 统计不同土地利用类型的面积/占比1.1 操作步骤Step1&#xff1a;Step2&#xff1a;计算面积Step3&#xff1a;计算占比 2 统计不同区域各类土地利用类型的面积2.1 操作步骤 3 土地利用变化转移矩阵3.1 研究思路3.2 操作步骤 4 分…

计算机毕业设计 智慧养老中心管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

3、SpringBoot_配置文件

四、配置文件 1.前言 曾经使用SpringMVC的时候是手动修改tomcat配置的端口信息&#xff0c;那现在Springboot如何修改&#xff1f;springboot有一个默认的配置文件 application.properties 2.配置文件分类 常用配置信息官方文档地址 https://docs.spring.io/spring-boot/doc…

【Vue.js】使用Element搭建登入注册界面axios中GET请求与POST请求跨域问题

一&#xff0c;ElementUI是什么&#xff1f; Element UI 是一个基于 Vue.js 的桌面端组件库&#xff0c;它提供了一套丰富的 UI 组件&#xff0c;用于构建用户界面。Element UI 的目标是提供简洁、易用、美观的组件&#xff0c;同时保持灵活性和可定制性 二&#xff0c;Element…