类和对象(c++)

news2024/11/24 20:40:17

欢迎来到本期频道!

类和对象

    • 定义:
    • 格式:
    • 类域:
    • 访问限定符
    • 友元
    • 内部类
    • this指针
    • 静态与非静态成员关系
    • 类型转换
    • 六大默认成员函数(C++98)
      • 1️⃣构造函数
      • 2️⃣拷贝构造函数
        • 浅拷贝与深拷贝
      • 3️⃣赋值重载拷贝函数
      • 4️⃣析构函数
      • 5️⃣取地址重载
      • 6️⃣const取地址重载
  • 对象
    • 类的实例过程
    • 对象的大小
    • 匿名对象
    • 初始化列表

定义:

C++程序设计允许程序员使用类(class)定义特定程序中的数据类型。

格式:

class 类名  {} ;

分号不可省略!

花括号{}中的内容称为类的成员;
类中的变量称为类的属性或成员变量;
类中的函数称为类的方法或成员函数;

类的成员变量有非静态成员变量和静态成员变量(static修饰);
类的成员函数有非静态成员函数和静态成员函数(static修饰);
例如:

class  Time
{
	void print(int hour,int minute)	//成员函数	方法
	{
		cout<<hour<<":"<<minute;
	}
	int _hour;	//成员变量   属性
	int _minute;
}
定义在类中的方法默认是inline函数

类域:

定义一个类,不仅仅只是定义了一个自定义类型,并且定义了一个新的作用域,既类域。

类的所有成员都在类的作用域中,既{}中;
如果在类外定义类成员时,需要使用作用域操作符::指定成员类域。

类域影响的是编译的查找规则

访问限定符

C++中一种实现封装的方式,用类将对象的属性和方法结合在一起,让对象更加完善,通过访问权限选择性的将其接口提供个外部的用户使用。

  • public
    • 该限定符修饰的成员在类外可直接访问
  • private
    • 该限定符修饰的成员在类外不能直接访问
  • protected
    • 该限定符修饰的成员在类外不能直接访问

创建类:

class  Time
{
public:	
	void Init(int hour,int minute)	//公有成员
	{
		_hour = hour;
		_minute = minute;
	}
	void print()	//公有成员
	{
		cout<<_hour<<":"<<_minute;
	}
private:	
	int _hour;	//私有成员
	int _minute;	//私有成员
};

小知识

struct也是定义类的关键字,只不过通常用class关键字,如果不写访问限定符,struct默认是public,class默认是private

这里先简单了解一下,类类型在物理内存中创建对象的过程,叫做类实例化出对象。

#include<iostream>
using namespace std;
class  Time
{
public:	
	void Init(int hour,int minute)	//公有成员
	{
		_hour = hour;
		_minute = minute;
	}
	void print()	//公有成员
	{
		cout<<_hour<<":"<<_minute;
	}
private:	
	int _hour;	//私有成员
	int _minute;	//私有成员
};
int main()
{
	Time t1;	//Time类实例化出t1对象
	int hour = 8;
	int minute = 30;
	t1.Init(hour,minute);	//调用公有成员Init()
	t1.print();			//调用公有成员print()
	return 0;
}

这里不能使用t1._hour是因为访问限定符private限制不能在类外直接访问。

#include<iostream>
using namespace std;

class  Time
{
public:	
	void Init(int hour,int minute)	//公有成员
	{
		_hour = hour;
		_minute = minute;
	}
	void print()	//公有成员
	{
		cout<<_hour<<":"<<_minute;
	}
private:	
	int _hour;	//私有成员
	int _minute;	//私有成员
};
int main()
{
	int hour1 = 8;
	int hour2 = 9;
	int minute1 = 30;
	int minute2 = 40;
	Time t1;	//Time类实例化出t1
	Time t2;	//Time类实例化出t2
	t1.Init(hour1,minute1);
	t2.Init(hour2,minute2);
	t1.print();
	t2.print();
	return 0;
}

友元

友元关键字friend,友元是一种突破类访问限定符封装的方式。
友元分为友元函数和友元类

性质:

  • 外部友元函数可以访问类的所有成员
  • 友元函数在类中仅仅是声明,不是类的成员函数
  • 友元函数可以在类定义的任何地方声明,不受类访问限定符的限制
  • 一个函数可以是多个类的友元函数
  • 友元类的成员函数都是友元函数
  • 友元类关系是单向的,没有交换性,没有传递性
class A
{
	friend class B;	//友元类
public:
	void print_a()
	{
		cout<<_a<<endl;
	}
private:
	int _a;
};
class B
{
	public:
	void print_b()		//是A的友元函数
	{
		A obj;
		
		obj.print_a();	//访问公有成员
		cout<<obj._a<<endl;	//访问私有成员
	}
};
虽然提供了便利,但是友元会增加耦合度,破坏了封装,不宜多用。

内部类

如果一个类定义在另一个类的内部,这个类放在内部的类叫做内部类。
性质:

  • 内部类是一个独立的类,与定义在全局的类相比,它只是受到类域和访问限定符的限制
  • 内部类默认是外部类的友元类
  • 内部类本质上是一种封装,当A类与B类紧密关联时,就可以考虑内部类

this指针

当t1调用Init和print时,成员函数是怎么知道是t1在调用,还是t2在调用呢?

其实编译器编译之后,都会在类的非静态成员函数的第一个形参位置添加一个当前类类型的指针,其真实原型为:

void Init(Time* const this, int hour, int minute);
void print(Time* const this, int hour, int minute);
类的非静态成员函数中访问成员变量,实质是通过this指针访问的。
那么能不能显示的传送指针或接收指针呢?
c++规定不能在实参和形参位置显示的写this指针(编译器编译时处理),但是可以在函数体内显示使用this指针。
class  Time
{
public:	
	void Init(int hour,int minute)	//公有成员
	{
		this->_hour = hour;			//只有类的非静态成员函数的函数体中可以显示写this
		this->_minute = minute;
	}
	void print()	//公有成员
	{
		cout<<this->_hour<<":"<<_minute;	//写或者不写都可以,效果一样
	}
private:	
	int _hour;	//私有成员
	int _minute;	//私有成员
};

静态与非静态成员关系

在类中除了普通成员变量和普通成员函数
还有const成员变量,const成员函数
以及static成员变量,static成员函数
让我们观察一下静态与非静态的关系
示例如下:

class wealth
{
public:
	void print()	//普通成员函数  wealth* const this
	{
		//可以修改所有非const成员变量
		_val = -1;
		_sval = -2;	

		//可以访问所有成员变量
		cout << _val << endl;
		cout << _cval << endl;	//	_cval本身有const属性不能直接修改
		cout << _sval << endl;

		//可以调用所有成员函数(因为普通类型的成员函数也可以调用)
		print_const();
		print_static();
	}

	void print_const()const	//const成员函数    const wealth* const this
	{
		//只能修改静态成员变量,因为_sval是通过类域指定的,而不是this指针
		_sval = -3;
		
		//可以访问所有成员变量
		cout << _val << endl;
		cout << _cval << endl;
		cout << _sval << endl;
		
		//只能调用static成员函数和自身const类型的成员函数
		print_static();
	}

	static void print_static()	//static成员函数		没有this指针
	{
		//没有this指针,无法访问或修改非静态成员变量以及非静态成员函数
		cout << _sval << endl;
		//只能访问或修改静态成员变量
		//只能调用静态成员函数
	}
private:
	//声明+缺省值
	int _val = 0;	//普通成员变量

	const int _cval = 1;	//const成员变量
	static int _sval;	//静态成员变量
};

int wealth::_sval = 2;

总结:

可访问
可访问
可访问
类的成员
非静态成员
静态成员
普通成员
const成员

类型转换

  • c++支持内置隐式类型转换为类类型对象,需要相关内置类型为参数的构造函数
class A
{
public:
	A(int x = 1,int y = 1)
	{
		_a = x;
	}
private:
	int _a;
	int _b;
};
int main()
{
	A obj;
	obj = 3;
	return 0;
}
  • 类类型的对象之间也可以隐式转换,需要相应的构造函数支持
class A
{
public:
	A(int x = 1)
	{
		_a = x;
	}
	int get_a()const
	{
		return _a;
	}
private:
	int _a; 
};
class B
{
public:
	B(const A& it,int c=1)
	{
		_b = it.get_a();
		_c = c;
	}
private:
	int _b;
	int _c;
};
  • 构造函数前加explicit关键字就不再支持隐式类型转换

六大默认成员函数(C++98)

如果小伙伴看到这里,可能觉得类好像知道的差不多了,但是为了更好的封装对象,在c++98中,类还有六大默认成员函数。

  • 构造函数
  • 拷贝构造函数
  • 赋值重载拷贝函数
  • 析构函数
  • 取地址重载
  • const取地址重载

默认成员函数:用户没有显示实现,编译器自动生成的函数
以Time类为例:

class  Time
{
public:	
	Time();								//构造函数
	Time(const Time& t);				//拷贝构造函数
	Time& operator=(const Time& t);		//赋值重载拷贝函数
	~Time();							//析构函数
	
	Time* operator&();					//取地址重载
	const Time* operator&()const;		//const取地址重载
private:	
	int _hour;
	int _minute;	
};

小知识

构造函数和析构函数不能加const

1️⃣构造函数

定义:
与普通函数相比,构造函数不写返回值,函数名是该类类型名称。

  • 构造函数分为默认构造和带参构造

  • 默认构造函数- - 有3种
    • 无参构造函数
      	Time()
      	{
      		//内容
      	}
      
    • 全缺省构造函数
      	Time(int hour = 1, int minute = 1)
      	{
      		//内容
      	}
      
    • 编译器自动生成的构造函数(没有显示写构造函数时才生成)

  • 带参构造函数
    Time(int hour,int miute=1)
    {
    	//内容
    }
    Time(int hour,int miute)
    {
    	//内容
    }
    Time(const Time& t)	//拷贝构造
    {
    	//内容
    }
    //.....等等
    

构造函数的功能是什么?

首先先看看构造函数的特点:

  • 函数名与类名相同
  • 不写返回值
  • 构造函数可以重载
  • 对象实例化时,自动调用对应的构造函数
  • 如果类中没有显示定义构造函数,C++编译器自动生成一个无参的默认构造函数。(如果显示定义了,就不生成了)
  • 默认构造函数只能存在一个或者没有,因为无参构造和全缺省构造虽然构成函数重载,但是存在调用歧义,所以二者只能留一个,既然显示定义了构造函数,那么就没有编译器生成的默认构造函数了;
    如果没有定义任何构造函数,编译器才会生成默认构造函数。
  • 编译器生成的默认构造函数对该类中的内置类型成员是否初始化取决于编译器,对类中的自定义类型,调用它的默认构造初始化。
我们可以从中得知构造函数是对象实例化时自动调用的特殊函数,通常用于初始化该类对象。

像Time类中内置类型没有指向资源的,可以按需要定义默认构造函数或者带参构造函数,可不写构造函数。

Time(int hour,int minute)
{
	_hour = hour;
	_minute = minute;
}

像stack类中内置类型指向资源的,最好建议使用默认构造函数,方便复用类型。

stack(int n = 4)
{
	_arr = new int[n];	//申请资源
	_size = 0;
	_capacity = n;
}

2️⃣拷贝构造函数

定义:
拷贝构造是一个特殊的构造函数.
要求第一个形参是自身类类型的引用,其余形参必须要有缺省值

Time(Time& t)
{
	//内容
}
Time(const Time& t)
{
	//内容
}
Time(const Time& t,int x = 1,int y = 2)
{
	//内容
}
//等等

拷贝构造是用一个已存在的对象去初始化一个新的对象
首先咱们看看拷贝构造函数的特点

  • 拷贝构造函数是一个特殊的构造函数(构造函数的重载)
  • 拷贝构造函数的第一个参数必须是当前类类型引用,如果使用传值方式,编译器直接报错(语法逻辑上引起无穷递归),其余参数必须有缺省值。
  • C++规定自定义类型对象进行拷贝时(传值传参、传值返回),必须调用其拷贝构造函数。
  • 如果没有显示定义拷贝构造函数,C++编译器会自动生成拷贝构造函数。
  • 编译器自动生成的拷贝构造函数,对类中内置类型是值拷贝(浅拷贝),对类中自定义类型是调用其拷贝构造。
浅拷贝与深拷贝
为什么会有深浅拷贝?

我们以栈为例:

class my_stack
{
public:
	my_stack(int n = 4)
	{
		_arr = new int[n];
		_size = 0;
		_capacity = n;
	}
	void push(int val)
	{
		if(_size==_capacity)
		{
			//...扩容
		}
		_arr[_size++] = val;
	}
	//......方便示例,简写
private:
	int* _arr;
	size_t _size;
	size_t _capacity;
};
int main()
{
	my_stack obj1(10);				//实例化出obj1
	for(size_t i = 0;i < 10; i++)	//在obj1中存储数据
	{
		obj1.push(i+1);
	}
	my_stack obj2(10);
	obj2 = obj1;		//将obj1拷贝给obj2
	return 0;
}

将obj1拷贝给obj2,我们的目的是让obj2拥有obj1一样的数据
第一种方式,就是浅拷贝:

obj2._arr = obj1._arr;
obj2._size = obj1._size;
obj2._capacity = obj1._capacity;

在这里插入图片描述
接下来,我们看看深拷贝:

obj2._arr = new int[obj1._capacity];
for(size_t i = 0; i < obj1._size; i++)
{
	obj2._arr[i] = obj1._arr[i];
}
obj2._size = obj1._size;
obj2._capacity = obj1._capacity;

在这里插入图片描述

总而言之,言而总之,有资源申请的类(或者有(释放资源的)析构函数),一定要用深拷贝,否则问题多多。

像Time类中的成员变量都没有指向资源的情况下,使用浅拷贝就可以了。(或者不写,编译器的就够用)

Time(const Time& t)
{
	_hour = t._hour;
	_minute = t._hour;
}

像Stack类中的成员变量_arr指向了堆的资源,需要我们手动的进行深拷贝。

#include<iostream>
using namespace std;
class stack
{
public:
    stack(int n = 4)
    {
        _arr = new int[n];
        _size = 0;
        _capacity = n;
    }
	//拷贝构造
	stack(const stack& st)
	{
		_arr = new int[st._size];	//申请一份新的资源空间
		for(size_t i = 0; i < st._size; i++)	//将st的资源空间的数据依次用赋值拷贝。
		{
			_arr[i] = st._arr[i];
		}
		//以上就是深拷贝

		_size = st._size;	//浅拷贝
		_capacity = st._capacity;	//浅拷贝
	}
	//.....为了方便示例,简写
private:
    int* _arr;
    size_t _size;
    size_t _capacity;
};

3️⃣赋值重载拷贝函数

定义:
C++支持使用operator关键字对运算符重载;该函数是对赋值运算符的重载。

赋值重载拷贝是用一个已存在的对象去拷贝一个已存在的对象。
让我们看看赋值重载拷贝函数的特点

  • 类类型的赋值运算符拷贝重载函数,规定必须重载为成员函数。
  • 返回值建议写成当前类类型的引用,可以减少拷贝且可以连续赋值。
  • 没有显示定义时,编译器会自动生成一个赋值重载拷贝函数,完成该类的浅拷贝。
  • 编译器自动生成的赋值重载拷贝函数,对类中的内置类型完成浅拷贝,对类中的自定义类型调用其赋值重载拷贝函数。
Time& operator=(const Time& t)
{
	//内容
}

既然是拷贝函数,那么也是分为浅拷贝和深拷贝
例如像Time类的成员变量没有指向任何资源,浅拷贝就可以了。

Time& operator=(const Time& t)	//形参和返回值用引用可以减少拷贝
{
	_hour = t._hour;
	_minute = t._minute;
	return *this;
}

像Stack类中的成员变量_arr指向了堆的资源,需要我们手动的进行深拷贝。

stack& operator=(const stack& st)
{
	delete[] _arr;			//释放旧空间
	_arr = new int[st._size];	//申请一份新的资源空间
	for(size_t i = 0; i < st._size; i++)	//将st的资源空间的数据依次用赋值拷贝。
	{
		_arr[i] = st._arr[i];
	}
	//以上就是深拷贝

	_size = st._size;	//浅拷贝
	_capacity = st._capacity;	//浅拷贝
	return *this;
}

4️⃣析构函数

定义:
与普通函数相比,析构函数不写返回值,没有形参(所以不支持函数重载),函数名是 ~类型名称。

析构函数特点:

  • 函数名是类名前加上字符~
  • 不写返回值,不写形参(没有重载函数)
  • 对象生命周期结束时,系统会自动调用析构函数
  • 当没有显示定义析构函数时,编译器会自动生成析构函数
  • 编译器自动生成的析构函数对类中的内置类型不做处理,对类中自定义类型成员会调用其析构函数
  • 即使用户显示定义了析构函数,对于类中的自定义类型成员也会调用其析构函数
  • 一个局部域的多个对象,C++规定先定义的后析构。

这里我们明白,无论写不写析构函数,对于类中的自定义类型都会调用其析构函数。
所以我们只要关心类中的内置类型是否指向资源即可。

~Time()
{
	//内容
}

像Time类中的内置类型成员变量,没有指向任何资源的,可以不写析构函数。

~Time()
{
	_hour = _minute = 0;
}

像stack类中的内置类型成员变量指向了资源的,必须手动写析构函数来释放资源。

~stack()
{
	delete[] _arr;	//释放资源
	_arr = nullptr;

	_size = _capacity = 0;
}

5️⃣取地址重载

定义:对取地址符号重载,用于获取普通对象地址。

Time* operator&()
{
	return this;
}

6️⃣const取地址重载

定义:对取地址符号重载,用于获取const对象地址。

怎么获取const对象的地址呢?前面我们说由于类中的非静态成员函数在经过编译之后,会在非静态成员函数的第一个形参位置添加this指针;

const Time* operator&(Time* const this)const;

该函数形参后面的const其实修饰的是*this,,我们把这类函数叫做const成员函数,它想表达的是这样:

const Time* operator&(const Time* const this);

但是c++规定合法的const成员函数如下:

const Time* operator&()const	//const修饰的是对象
{
	return this;
}

对象

类的实例过程

前面我们稍微提到了类的实例化,那么实例化大致是什么样的一个过程呢?
事实上,一个类对象会在编译期间开辟好空间并对类的静态成员变量初始化,接着走初始化列表对类的非静态成员变量进行初始化,然后进入构造函数的函数体完成相关指令,从而得到一个完整的对象。

对象的大小

对象是由类实例化而来,而类中有变量和函数。


事实上在编译器编译之后,代码会编译成指令,这里类中的函数地址,其实不需要存储,这些函数都在代码区,不存在于对象中。


那么变量呢?
其实静态成员变量存在静态区,是整个类的共享变量,所以静态成员变量也不属于某个对象。

而非静态成员变量存在栈中,编译时开好的空间,就是为非静态成员变量开的,那么非静态成员变量有好几个,在这个对象的空间中,是随便放的吗?显然不是,不仅是按照声明顺序存储的,而且还要按照内存对齐规则存储。


class my_type
{
public:
	my_type(int val = 1, float fval = 1.0)
	{
		_val = val;
		_fval = fval;
	}
	void print()	//非静态
	{
		cout<<_val<<endl;
		cout<<_fval<<endl;
		cout<<_sval<<endl;
	}
	static void print_s()	//静态
	{
		cout<<_sval<<endl;
	}
	
private:
	int _val;
	float _fval;	//非静态

	static int _sval;		//静态
};
int my_type::_sval = 1;

匿名对象

用类型(实参)定义出来的对象叫做匿名对象。

int main()
{
	Time(8,30).print();	//匿名对象调用方法
	return 0;
}

性质:

匿名对象的生命周期只在当前一行。

初始化列表

什么是初始化列表?不是说构造函数是用来初始化的吗?

初始化列表是在构造函数参数列表后以一个冒号开始,接着用逗号分隔的数据成员列表,每个初始化列表成员后跟一个放在圆括号中的初始值或表达式。

初始化列表是用来初始化对象的。

class Time
{
public:
	Time(int hour,int minute)
	{
		_hour = hour;
		_minute = minute;	
	}
	//...
private:
	int _hour;
	int _minute;
};

class luck
{
public:
	luck(int val, int cval,int& ref, int hour, int minute)
	:_val(val)					//初始化列表
	,_cval(cval)
	,_ref(ref)
	,_t(hour,minute)
	{
	}
	//...
private:
	int _val;	
	
	const int _cval;	//const成员变量
	int& _ref;			//引用
	Time _t;			//无默认构造函数的自定义类型
	
	static int _sval;
	static const int _scval;
};
int luck::_sval = 1;		//静态成员变量在类外初始化
const int luck::_scval = 1;
为什么静态成员变量不能出现在初始化列表中?

前面提到静态成员变量不在某个对象中,而初始化列表是用来初始化某个对象的(也就是对象这快空间),所以它不走初始化列表。

由以上可知初始化列表在语法上,可认为是每个非静态成员变量定义初始化的地方。
而构造函数体内使用的是赋值。

像Time类的构造函数并没有写初始化列表,但事实上,在进入构造函数体之前,每个非静态成员变量都会按声明顺序依次经过初始化列表,只不过在没有写初始化列表的情况下,对内置类型是否初始化取决于编译器,对自定义类型调用其默认构造函数;但是const成员变量引用无默认构造的自定义类型必须出现在初始化列表中。

无论有没有显示写,每个构造函数都有初始化列表。

注意:

初始化列表是按照声明顺序初始化的。

希望该片文章对您有帮助,请点赞支持一下吧😘💕

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

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

相关文章

x-cmd pkg | superfile: 终端文件管理器,界面精致美观

目录 简介快速上手功能特点竞品和相关项目进一步阅读 简介 superfile 是 github.com/yorukot 用 Go 开发的终端文件管理器&#xff0c;相比于其他终端文件管理器&#xff0c;它最显著的特点是 UI 精致美观。 Tip Superfile 采用了特殊的 Unicode 符号来标识各种类型的文件&…

【我的 PWN 学习手札】Unsortedbin Leak

前言 从前都是野路子学习&#xff0c;学校时间也比较紧张&#xff0c;没有能够好好总结。一直有做个人笔记的习惯&#xff0c;但是学习路线比较分散盲目&#xff0c;虽然跟着wiki做&#xff0c;但是也面临知识点不全的窘境。近期开始跟着课程系统的学习&#xff0c;对于老的知…

mp3转文字要怎么处理?使用这4个工具就对了

MP3是音频当中比较常用的格式&#xff0c;如果像将其转换成文字内容&#xff0c;一般的语音转文字工具都是可以完成的。但是音频转换成文字的过程中&#xff0c;它的准确率是会受到像口音&#xff0c;语言&#xff0c;环境音等因素的影响的。所以大家如果想将自己的mp3语音转成…

en造数据结构与算法C# 用数组实现个栈还不简单???看我一秒破之!!!(unity演示)

实现效果 线性表&#xff0c;线性表是指数据元素按顺序排列的一种数据结构&#xff0c;下面这些东西可以说都是线性表&#xff0c;所以用array实现三者一点问题都没有 分别是List动态数组&#xff0c;stack栈和queue队列&#xff0c;今天就秒掉stack 栈&#xff1a;先进后出 实…

Vue邮件发送:如何有效集成邮件发送功能?

vue邮件发送功能实现方法&#xff1f;Vue邮件发送性能怎么优化&#xff1f; 无论是用户注册验证、密码重置&#xff0c;还是通知提醒&#xff0c;邮件发送功能都能提供重要的支持。本文将详细探讨如何在Vue项目中有效集成邮件发送功能&#xff0c;确保邮件能够准确、及时地送达…

万龙觉醒免费辅助:VMOS云手机辅助巴克尔阵容搭配攻略!

《万龙觉醒》是一款策略类手游&#xff0c;选择合适的英雄阵容搭配能够极大提升战斗效果。而借助VMOS云手机的辅助功能&#xff0c;玩家可以更加轻松地管理游戏进程&#xff0c;优化操作体验。以下是VMOS云手机的三大核心功能&#xff0c;帮助你更好地掌控《万龙觉醒》战局。 V…

通信工程学习:什么是QoS服务质量

QoS服务质量 在通信工程中&#xff0c;QoS&#xff08;Quality of Service&#xff0c;服务质量&#xff09;是一个至关重要的概念&#xff0c;它关乎网络性能的提升和用户体验的优化。QoS是网络的一种安全机制&#xff0c;旨在通过一系列技术和策略来优化网络资源的分配&#…

代码随想录打卡Day30

今天的题目还可以&#xff0c;第一题看了视频&#xff0c;看卡哥把问题转化成数学问题&#xff0c;把图画出来以后就会了&#xff0c;剩下两题没看视频直接AC的。 452. 用最少数量的箭引爆气球 这个题主要是画完图以后就很好理解了&#xff0c;需要先对区间按照区间左值进行排…

飞速了解Conda的作用和安装使用教程

当我们想要在github上克隆不同的项目下来运行时&#xff0c;会发现项目的语言环境或包的版本不同&#xff0c;出现版本冲突问题会导致程序无法运行、兼容性问题频出。我们常常需要管理多个项目&#xff0c;每个项目可能依赖于不同的包版本或编程语言环境。如果不加以管理&#…

华为OD机试 - 报文响应时间 - 贪心算法、位运算(Java 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;E卷D卷A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加…

基于SpringBoot的准妈妈孕期交流平台

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架 工具&#xff1a;IDEA/Eclipse、Navicat 系统展示 首页 管理员登录 用户管理 早教…

C++ STL关联容器Set与集合论入门

1. 简介 Set&#xff08;集合&#xff09;属于关联式容器&#xff0c;也是STL中最实用的容器&#xff0c;关联式容器依据特定的排序准则&#xff0c;自动为其元素排序。Set集合的底层使用一颗红黑树&#xff0c;其属于一种非线性的数据结构&#xff0c;每一次插入数据都会自动…

【F的领地】项目拆解:小学教辅资料

项目介绍 虚拟资料项目的赛道其实一直可以做&#xff0c;实际上就是一个信息差项目。 知识付费是常青树&#xff0c;人天生有为知识付费的倾向。 而且虚拟资料通常一份 19~99 的资料有这方面需求很容易就能付款。 主要是产附属的流量再提问题。 我有个同乡&#xff0c;18年…

DDOS攻击学习-scapy使用python编写SYN拒绝服务攻击

文章目录 启动&配置发送数据怎么查看回答查看详细的数据sinff()hexdump() 使用python进行SYN拒绝服务攻击 安装npcap可以查看此教程 启动&配置 scapy#控制台输入如图所示可以查看IP等, 格式是 变量名 IP()/TCP()你可以查看相关信息 变量名.show()以上的值都可以进行…

2024第三届大学生算法大赛 真题训练2 解题报告 | 珂学家 | FFT/NTT板子

前言 题解 D是FFT板子题&#xff0c;这么来看&#xff0c;其实处于ACM入门题&#xff0c;哭了T_T. D. 行走之谜 思路: FFT 如果你知道多项式乘法&#xff0c;继而知道FFT&#xff0c;那题纯粹就是板子题&#xff0c;可惜当时比赛的时候&#xff0c;无人AC。 这题来简单抽象…

最好磁吸充电宝是哪个牌子?目前公认好用磁吸充电宝排行榜!

在现代生活中&#xff0c;移动设备的普及使得充电宝成为了人们日常出行必备的工具。尤其是磁吸充电宝&#xff0c;以其便捷的使用体验和高效的充电速度&#xff0c;逐渐受到消费者的青睐。然而&#xff0c;在选择充电宝时&#xff0c;安全性能是不可忽视的重要因素。一个好的充…

Redis入门1

Redis简介 Redis是一个基于内存的 key-value 结构数据库。 基于内存存储&#xff0c;读写性能高 适合存储热点数据(热点商品、资讯、新闻) 企业应用广泛 官网:https://redis.io 中文网:https://www.redis.net.cn/ window版启动命令 redis-server.exe redis.windows.con…

使用dnSpy调试服务端IIS部署的WebService的程序集

服务器上部署的C#编写WebService出现问题&#xff0c;需要排查&#xff0c;但没有对应的源码&#xff0c;只能在服务器端想办法调试。   IIS中部署的WebService服务&#xff0c;其应用程序池对应操作系统中的w3p.exe进程&#xff08;高版本IIS对应的进程是w3wp&#xff09;。…

[001-02-001]. 第07-03节:理解线程的安全问题

我的后端学习大纲 我的Java学习大纲 当多个线程共享一份数据的时候&#xff0c;不同的线程对数据进行操作&#xff0c;就可能会导致线程安全问题&#xff0c;比如卖票过程中出现了错票和重复票的问题&#xff1a; 1、卖票问题分析&#xff1a; 1.1.理想状态&#xff1a; 1.2.极…

软考架构-面向服务的架构风格

一、SOA 1、概念 面向服务开发&#xff0c;服务之间通过简单、精确定义接口进行通信&#xff0c;不涉及底层编程接口和通信模型。多个服务挂载在ESB&#xff08;企业服务总线&#xff09;上进行通信。 2、特征 可从企业外部访问、随时可用&#xff08;服务请求能被及时响应…