C++类和对象 - 下【匿名对象,友元,static成员】

news2024/12/28 21:30:06


 🌟个人主页:落叶

  🌟当前专栏: C++专栏


目录

​编辑

再探构造函数

类型转换 

 static成员

友元 

 内部类

匿名对象

对象拷⻉时的编译器优化


再探构造函数

  • 之前我们实现构造函数时,初始化成员变量主要使⽤函数体内赋值,构造函数初始化还有⼀种⽅式,就是初始化列表,初始化列表的使⽤⽅式是以⼀个冒号开始,接着是⼀个以逗号分隔的数据成员列表,每个"成员变量"后⾯跟⼀个放在括号中的初始值或表达式

  • 每个成员变量在初始化列表中只能出现⼀次,语法理解上初始化列表可以认为是每个成员变量定义初始化的地⽅。

  • 引⽤成员变量const成员变量没有默认构造的类类型变量必须放在初始化列表位置进⾏初始化,否则会编译报错

  • C++11⽀持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显⽰在初始化列表初始化的成员使⽤的

  • 尽量使⽤初始化列表初始化,因为那些你不在初始化列表初始化的成员也会⾛初始化列表,如果这个成员在声明位置给了缺省值,初始化列表会⽤这个缺省值初始化。如果你没有给缺省值,对于没有显⽰在初始化列表初始化的内置类型成员是否初始化取决于编译器,C++并没有规定。对于没有显⽰在初始化列表初始化的⾃定义类型成员会调⽤这个成员类型的默认构造函数,如果没有默认构造会编译错误

  • 初始化列表中按照成员变量在类中声明顺序进⾏初始化跟成员在初始化列表出现的的先后顺序⽆关。建议声明顺序和初始化列表顺序保持⼀致

初始化列表的使⽤⽅式是以⼀个冒号开始,接着是⼀个以逗号分隔的数据成员列表,每个"成员变量"后⾯跟⼀个放在括号中的初始值或表达式

  • 引⽤成员变量const成员变量没有默认构造的类类型变量必须放在初始化列表位置进⾏初始化,否则会编译报错

像栈这种,如果想传参数过去初始化,那就必须用初始化列表进行初始化。


C++11⽀持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显⽰在初始化列表初始化的成员使⽤的

当初始化列表内没有显⽰初始化,初始化列表会使用缺省值初始化。


 初始化列表中按照成员变量在类中声明顺序进⾏初始化跟成员在初始化列表出现的的先后顺序⽆关。建议声明顺序和初始化列表顺序保持⼀致

下⾯程序的运⾏结果是什么()

A.输出  1  1
B.输出  2  2 
C.编译报错
D.输出  1  随机值
E.输出  1  2
F.输出  2  1

#include<iostream>
using namespace std;
class A
{
public:
	A(int a)
		:_a1(a)
		,_a2(_a1)
	{}

	void Print() {
		cout << _a1 << " " << _a2 << endl;
	}

private:
	int _a2 = 2;
	int _a1 = 2;
};

int main()
{
	A aa(1);
	aa.Print();
}

是按照成员变量的顺序,进行初始化的,_a1现在没有被初始化,所以是随机值。

再到a1初始化的时候,初始化为a的值。

答案是:D

1和随机值


类型转换 

  • C++⽀持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数
  • 构造函数前⾯加explicit就不再⽀持隐式类型转换
  • 类类型的对象之间也可以隐式转换,需要相应的构造函数⽀持

这个1会生成一个A的临时对象,然后再拷贝给aa1

经过编译器的优化,编译器遇到连续构造+拷⻉构造->优化为直接构造

下面我们可以看到,没走拷贝构造。

运行结果:


 这1会生成引用的临时对象,前面会有个const,直接构造给aa2那不就是权限放大吗。

加个const就行了


如果我们不需要类型转换,可以在前面加explicit。


多参数的对象,会找到多参数的成员函数,直接构造。


假设我们有一个栈,我们可以直接用类型转换进行入栈了。


内置类型 -> 自定义类型的转换
自定义类型 -> 自定义类型转换

代码:

#include<iostream>
using namespace std;
class A
{
public:
	// 构造函数explicit就不再⽀持隐式类型转换
	// explicit A(int a1)
	A(int a1)
		:_a1(a1)
	{
		cout << "构造函数:A(int a1)" << endl;
	}

	//拷贝构造
	A(const A& d)
		:_a1(d._a1)
		, _a2(d._a2)
	{
		cout << "拷贝构造:A(const A& d)" << endl;
	}

	void Print()
	{
		cout << _a1 << " " << _a2 << endl;
	}

	A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{
		cout << "构造函数:A(int a1,int a2)" << endl;
	}
	int Get() const
	{
		return _a1 + _a2;
	}

private:
	int _a1 = 1;
	int _a2 = 99;
};

class B
{
public:
	B(const A& a)
		:_b(a.Get())
	{}
private:
	int _b = 0;
};

class Stack
{
public:
	void Push(const A& aa)
	{}
//...
};
// 内置类型 -> 自定义类型的转换
// 自定义类型 -> 自定义类型转换
int main()
{
	// 1构造⼀个A的临时对象,再⽤这个临时对象拷⻉构造aa3
	// 编译器遇到连续构造+拷⻉构造->优化为直接构造
	/*A aa1 = 1;
	aa1.Print();

	const A& aa2 = 1;*/

	A aa3 = { 2,2 };
	const A& aa4 = { 1,1 };

	//栈
	Stack st;
	/*A aa5(5);
	st.Push(aa5);*/
	st.Push(5);

	/*A aa6(6,6);
	st.Push(aa6);*/
	st.Push({ 6,6 });

	// aa3隐式类型转换为b对象
    // 原理跟上⾯类似
	B b = aa3;
	const B& rb = aa3;

	return 0;
}

 static成员

  • ⽤static修饰的成员变量,称之为静态成员变量,静态成员变量⼀定要在类外进⾏初始化
  • 静态成员变量为所有类对象所共享,不属于某个具体的对象,不存在对象中,存放在静态区。
  • ⽤static修饰的成员函数,称之为静态成员函数,静态成员函数没有this指针
  • 静态成员函数中可以访问其他的静态成员,但是不能访问⾮静态的,因为没有this指针
  • ⾮静态的成员函数,可以访问任意的静态成员变量和静态成员函数
  • 突破类域就可以访问静态成员,可以通过类名::静态成员 或者 对象.静态成员 来访问静态成员变量和静态成员函数。
  • 静态成员也是类的成员,受public、protected、private 访问限定符的限制
  • 静态成员变量不能在声明位置给缺省值初始化,因为缺省值是给构造函数初始化列表的,静态成员变量不属于某个对象不⾛构造函数初始化列表

⽤static修饰的成员变量,就是静态成员变量,静态成员变量必须要在类外进行初始化。

class Date
{
public:
	Date(int& x, int year = 1, int month = 1, int day = 1)
	{
	}
private:
	int _year;
	int _month;

	//静态成员变量
	static int _day;

};

//必须要在类外进行初始化
int Date::_day = 10;

int main()
{
	Date d1();
	return 0;
}

⽤static修饰的成员函数,称之为静态成员函数,静态成员函数没有this指针

静态成员函数中可以访问其他的静态成员,但是不能访问⾮静态的,因为没有this指针


 ⾮静态的成员函数,可以访问任意的静态成员变量和静态成员函数


突破类域就可以访问静态成员,可以通过类名::静态成员 或者 对象.静态成员 来访问静态成员变量和静态成员函数。


class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
		:_year(10)
		,_month(7)
	{
	}
	//静态成员函数
	const int Print() 
	{
		return _day;
	}

private:
	int _year = 12;
	int _month = 6;

	//静态成员变量
	static int _day;

};

//必须要在类外进行初始化
int Date::_day = 10;

void fun()
{
	//如果是一个函数的话我们用,对象.静态成员函数,还要创建一个对象太麻烦了。
	
	//可以使用类名::静态成员函数
	cout << Date::Print << endl;
}

int main()
{
	Date d1;
	//对象.静态成员函数
	cout << d1.Print() << endl;

	return 0;
}

静态成员也是类的成员,受public、protected、private 访问限定符的限制 

静态的成员所有类都能进行访问,但还是会受到public、protected、private 访问限定符的限制。


静态成员变量不能在声明位置给缺省值初始化,因为缺省值是给构造函数初始化列表的,静态成员变量不属于某个对象不⾛构造函数初始化列表

我们可以看到已经报错了。


代码: 

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
		:_year(10)
		,_month(7)
	{
	}
	//静态成员函数
	const int Print() 
	{
		return _day;
	}

private:
	int _year = 12;
	int _month = 6;

	//静态成员变量
	static int _day;
	//static int _day = 10;

};

//必须要在类外进行初始化
int Date::_day = 10;

void fun()
{
	//如果是一个函数的话我们用,对象.静态成员函数,还要创建一个对象太麻烦了。
	
	//可以使用类名::静态成员函数
	cout << Date::Print << endl;
}

int main()
{
	Date d1;
	//对象.静态成员函数
	cout << d1.Print() << endl;

	return 0;
}

求1+2+3+...+n_牛客题霸_牛客网 (nowcoder.com)

代码:

#include <type_traits>
class add{
public:
   //构造函数
   add()
   {
       //每调用一次,d2都会加d1
       d2 = d2 + d1;
       d1++;
   }
   //静态成员函数
   static int tab()
   {
      return d2;
   }
private:
//静态成员
 static int d1;
 static int d2;
};
//静态成员初始化d1和d2
int add::d1 = 1;
int add::d2 = 0;
 
class Solution {
public:
    int Sum_Solution(int n) {
        //这里的n,是有n个对象,每个对象都会调用构造函数
        add ss[n];
        //返回d2的值
        return add::tab();
    }
};

设已经有A,B,C,D 4个类的定义,程序中A,B,C,D构造函数调⽤顺序为()
设已经有A,B,C,D 4个类的定义,程序中A,B,C,D析构函数调⽤顺序为()

A:D B A C
B:B A D C
C:C D B A
D:A B D C
E:C A B D
F:C D A B  


C c;
int main()
{
A a;
B b;
static D d;
return 0;
}

构造函数调⽤顺序为:E

是先构造全局的C,然后再构造main函数里的。

析构函数调⽤顺序为:B

C和D类生命周期是全局的,析构先析构A和B类,从下往上析构,再析构D和E。


友元 

  • 友元提供了⼀种突破类访问限定符封装的⽅式,友元分为:友元函数和友元类,在函数声明或者类 
  • 声明的前⾯加friend,并且把友元声明放到⼀个类的⾥⾯
  • 外部友元函数访问类的私有和保护成员,友元函数仅仅是⼀种声明他不是类的成员函数
  • 友元函数可以在类定义的任何地⽅声明,不受类访问限定符限制
  • ⼀个函数可以是多个类的友元函数。
  • 友元类中的成员函数都可以是另⼀个类的友元函数,都可以访问另⼀个类中的私有和保护成员
  • 友元类的关系是单向的,不具有交换性,⽐如A类是B类的友元,但是B类不是A类的友元
  • 友元类关系不能传递,如果A是B的友元,B是C的友元,但是A不是C的友元。
  • 有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多⽤。

举例:A和B它们家是别墅,家里都有保安,成员变量是游泳池,

友元声明就是和保安说,func是我的朋友,他可以来我家游泳池(成员变量访问)玩。

A和B都友元声明了func,这样func就都可以访问它们的成员变量了。

#include<iostream>
using namespace std;
// 前置声明,都则A的友元函数声明编译器不认识B 
class B;
class A
{
	// 友元声明 
	friend void func(const A& aa, const B& bb);

private:
	int _a1 = 1;
	int _a2 = 2;
};
class B
{
	// 友元声明 
	friend void func(const A& aa, const B& bb);

private:
	int _b1 = 3;
	int _b2 = 4;
};

void func(const A& aa, const B& bb)
{
	cout << aa._a1 << endl;
	cout << bb._b1 << endl;
}
int main()
{
	A aa;
	B bb;
	func(aa, bb);
	return 0;
}

A类里友元声明了B,B类里可以访问,B的成员变量也可以访问A的成员变量。

#include<iostream>
using namespace std;

class A
{
	// 友元声明
	friend class B;
private:
	int _a1 = 1;
	int _a2 = 2;
};

class B
{
public:
	void func1(const A& aa)
	{
		cout << aa._a1 << endl;
		cout << _b1 << endl;
	}
	void func2(const A& aa)
	{
		cout << aa._a2 << endl;
		cout << _b2 << endl;
	}
private:
	int _b1 = 3;
	int _b2 = 4;
};
int main()
{
	A aa;
	B bb;
	bb.func1(aa);
	bb.func1(aa);
	return 0;
}

  • 友元类的关系是单向的,不具有交换性,⽐如A类是B类的友元,但是B类不是A类的友元
  • 友元类关系不能传递,如果A是B的友元,B是C的友元,但是A不是C的友元。
  • 有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多⽤。

 内部类

  • 如果⼀个类定义在另⼀个类的内部,这个内部类就叫做内部类。内部类是⼀个独⽴的类跟定义在全局相⽐,他只是受外部类类域限制访问限定符限制,所以外部类定义的对象中不包含内部类。
  • 内部类默认是外部类的友元类
  • 内部类本质也是⼀种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使⽤,那么也可以考虑把A类设计为B的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类,其他地⽅都⽤不了。

在A内部定义B,跟定义在全局相⽐,他只是A类类域限制访问限定符限制,

B类默认是A类的友元类,B这个内部类可以访问A类的私有成员。

A类类域限制访问限定符限制,要定义B对象时,要在B前面加访问限定符    A::B bb;

class A
{
	//在A内部定义B
	class B
	{
	public:

		void func1(const A& aa)
		{
			cout << aa._a1 << endl;
			cout << _b1 << endl;
		}

		void func2(const A& aa)
		{
			cout << aa._a2 << endl;
			cout << _b2 << endl;
		}

	private:
		int _b1 = 3;
		int _b2 = 4;
	};


private:
	int _a1 = 1;
	int _a2 = 2;
};

int main()
{
	//cout << sizeof(A) << endl;

	A aa;
	A::B bb;
	bb.func1(aa);
	bb.func1(aa);
	return 0;
}

我们可以看到A类是8,没有计算B类的成员,B类实际上是在全局,只是A类类域限制访问限定符限制。

在C++里用内部类还是比较少的,JAVA用得比较多。 


匿名对象

  • 类型(实参) 定义出来的对象叫做匿名对象,相⽐之前我们定义的  类型 对象名(实参) 定义出来的叫有名对象
  • 匿名对象⽣命周期只在当前⼀⾏,⼀般临时定义⼀个对象当前⽤⼀下即可,就可以定义匿名对象。

匿名对象就是没有名字的

定义匿名必须要有括号。

有名对象,就是有名字的

匿名对象他的⽣命周期只有当前这⼀⾏,下⼀⾏他就会⾃动调⽤析构函数。


以前我们调用类里的函数,需要创建对象,再去访问函数。

匿名对象,可以直接进行访问。

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a)" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
class Solution {
public:
	int Sum_Solution(int n) {
		//...
		return n;
	}
};
int main()
{
	A aa1;
	// 不能这么定义对象,因为编译器⽆法识别下⾯是⼀个函数声明,还是对象定义
	//A aa1();
	// 但是我们可以这么定义匿名对象,匿名对象的特点不⽤取名字,
	// 但是他的⽣命周期只有这⼀⾏,我们可以看到下⼀⾏他就会⾃动调⽤析构函数
	A(1);
	A();
	A aa2(2);
	// 匿名对象在这样场景下就很好⽤,当然还有⼀些其他使⽤场景,这个我们以后遇到了再说
	Solution().Sum_Solution(10);

    //Solution dd;
    //dd.Sum_Solution(5);

	return 0;
}

类类型的行参,需要缺省参数,那就需要到匿名对象了。

class A
{
public:

private:
	int _a;
};

class Solution {
public:
    //类类型缺省参数
	void  Sum_Solution(const A& d = A()) 
	{
		//..
	}
};
int main()
{  
    A aa1;

    Solution().Sum_Solution(aa1);

	return 0;
}

对象拷⻉时的编译器优化

  • 现代编译器会为了尽可能提⾼程序的效率,在不影响正确性的情况下会尽可能减少⼀些传参和传返回值的过程中可以省略的拷⻉。
  • 如何优化C++标准并没有严格规定,各个编译器会根据情况⾃⾏处理。当前主流的相对新⼀点的编译器对于连续⼀个表达式步骤中的连续拷⻉会进⾏合并优化,有些更新更"激进"的编译器还会进⾏跨⾏跨表达式的合并优化。
#include<iostream>
using namespace std;
class A
{
public:
	A(int a = 0)
		:_a1(a)
	{
		cout << "A(int a)" << endl;
	}
	A(const A& aa)
		:_a1(aa._a1)
	{
		cout << "A(const A& aa)" << endl;
	}
	A& operator=(const A& aa)
	{
		cout << "A& operator=(const A& aa)" << endl;
		if (this != &aa)
		{
			_a1 = aa._a1;
		}
		return *this;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a1 = 1;
};
void f1(A aa)
{}
A f2()
{
	A aa;
	return aa;
}
int main()
{
	// 传值传参
	A aa1;
	f1(aa1);
	cout << endl;
	// 隐式类型,连续构造+拷⻉构造->优化为直接构造
	f1(1);
	// ⼀个表达式中,连续构造+拷⻉构造->优化为⼀个构造
	f1(A(2));
	cout << endl;
	cout << "***********************************************" << endl;
	// 传值返回
// 返回时⼀个表达式中,连续拷⻉构造+拷⻉构造->优化⼀个拷⻉构造 (vs2019 debug)
// ⼀些编译器会优化得更厉害,进⾏跨⾏合并优化,直接变为构造。(vs2022 debug)
	f2();
	cout << endl;
	// 返回时⼀个表达式中,连续拷⻉构造+拷⻉构造->优化⼀个拷⻉构造 (vs2019 debug)
	// ⼀些编译器会优化得更厉害,进⾏跨⾏合并优化,直接变为构造。(vs2022 debug)
	A aa2 = f2();
	cout << endl;
	// ⼀个表达式中,连续拷⻉构造+赋值重载->⽆法优化
	aa1 = f2();
	cout << endl;
	return 0;
}

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

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

相关文章

Mac 远程 Windows 等桌面操作系统工具 Microsoft Remote Desktop for Mac 下载安装详细使用教程

最近需要在 Mac 上远程连接控制我的 windows 电脑系统&#xff0c;经过一番尝试对于 win 来说还是微软自家推出的 Microsoft Remote Desktop for Mac 最最好用&#xff0c;没有之一 简介 Microsoft Remote Desktop是一款由微软公司开发的远程桌面连接工具&#xff0c;可以让用…

Redis遇到Hash冲突怎么办?

这是小伙伴之前遇到的一个面试题&#xff0c;感觉也是一个经典八股&#xff0c;和大伙分享下。 一 什么是 Hash 冲突 Hash 冲突&#xff0c;也称为 Hash 碰撞&#xff0c;是指不同的关键字通过 Hash 函数计算得到了相同的 Hash 地址。 Hash 冲突在 Hash 表中是不可避免的&am…

开源图像超分ECBSR项目源码分析

相关介绍 项目GitHub地址&#xff1a;https://github.com/xindongzhang/ECBSR项目相关论文&#xff1a;https://www4.comp.polyu.edu.hk/~cslzhang/paper/MM21_ECBSR.pdf&#xff08;也可以点这里下载&#xff09;论文解读&#xff1a;Edge-oriented Convolution Block for Re…

CLion远程开发Ubuntu,并显示helloworld文字框

1.CLion的介绍以及其在远程开发上的优点 1&#xff09;CLion 是一个由 JetBrains 开发的跨平台 C/C 集成开发环境&#xff08;IDE&#xff09;&#xff0c;功能强大。 2&#xff09;CLion的优点&#xff1a; 远程工具链支持&#xff1a;CLion 支持通过 SSH 连接到远程 Ubuntu…

Unity--AssestBundles--热更新

使用Node.js搭建AssestBundle服务器并验证AB包热更新 一、服务器部分 使用NodeJs作为服务器&#xff0c; 使用Express为基础网页模版。 当然&#xff0c; 使用其他的FTP&#xff0c;http服务器也可以&#xff0c; 基础逻辑是存放资源的位置。 1.下载Node.js 下载地址:https…

【Python】NumPy(二):数组运算、数据统计及切片索引、广播机制

目录 Numpy数组 数组的基本运算 乘法 加法 数组的数据统计 平均值 中位数 最大值和最小值 求和 累积和 标准差 方差 切片和索引 索引 一维数组的索引 二维数组的索引 获取多个元素 布尔索引 切片 一维数组切片 二维数组切片 多维数组切片 广播机制 规则 …

本地生活便民信息服务小程序源码系统 PHP+MySQL组合开发 带完整的安装代码包以及搭建部署教程

系统概述 地方门户分类信息网站源码系统是一个基于PHP和MySQL开发的强大平台&#xff0c;旨在帮助用户轻松搭建地方性的分类信息网站。该系统集成了众多实用功能&#xff0c;支持用户自由发帖、浏览和搜索各类信息&#xff0c;如二手交易、求职招聘、房屋租售、生活服务、商家…

【java】抽象类和接口(了解,进阶,到全部掌握)

各位看官早安午安晚安呀 如果您觉得这篇文章对您有帮助的话 欢迎您一键三连&#xff0c;小编尽全力做到更好 欢迎您分享给更多人哦 大家好我们今天来学习Java面向对象的的抽象类和接口&#xff0c;我们大家庭已经来啦~ 一&#xff1a;抽象类 1.1:抽象类概念 在面向对象的概念中…

练习题(动态规划)

一&#xff0c;最长上升子序列2 题目&#xff1a; 思路分析&#xff1a; 之前的最长上升子序列的时间度是O(n^2)&#xff0c;同时集合划分是按以第 i - 1 个数是几来划分的&#xff0c;状态转移方程也很简单是 f[i] f[j] 1 &#xff0c;最后取所有一个max 那怎么优化呢&am…

ST7789读取ID错误新思路(以STC32G为例)

1.前言 前两天刚把ST7789写入搞定&#xff0c;这两天想折腾一下读取。最开始是读ID&#xff0c;先是用厂家送的程序&#xff0c;程序里面用的是模拟I8080协议&#xff0c;一切正常。后来我用STC32G的内置LCM模块&#xff0c;发现读取不出来。更神奇的是ID读不出来&#xff0c;…

【AIGC】AI如何匹配RAG知识库: Embedding实践,语义搜索

引言 RAG作为减少模型幻觉和让模型分析、回答私域相关知识最简单高效的方式&#xff0c;我们除了使用之外可以尝试了解其是如何实现的。在实现RAG的过程中Embedding是非常重要的手段。本文将带你简单地了解AI工具都是如何通过Embedding去完成语义分析匹配的。 Embedding技术简…

HTB:Headless[WriteUP]

目录 连接至HTB服务器并启动靶机 1.Which is the highest open TCP port on the target machine? 2.What is the title of the page that comes up if the site detects an attack in the contact support form? 使用浏览器访问靶机5000端口 3.What is the name of the …

海量数据在有限资源上处理的方法

1. 使用哈希 适用场景&#xff1a;需要处理的数据中&#xff0c;相同的数据可以分配到同样的机器/文件进行处理。 技巧总结&#xff1a;相同的数会哈希到同一个位置上 这类题目一般面试官给的描述都不是很清晰&#xff0c;需要自己去问条件、然后给出方案。 回答思路是&#…

hdfs的客户端(big data tools插件)

1.下载hadoop的压缩包在Windows,后解压 2.下载hadoop.dll文件和winutil.exe文件(网上自行查找) 下载完把这两个文件放入hadoop的bin目录 3.设置环境变量: $HADOOP_HOME指向hadoop的文件夹 4.在jetbrains公司的软件里下载big data tools插件:(在此展示的idea的) 下载完重启ide…

AI金融攻防赛:YOLO模型的数据增强与性能优化(DataWhale组队学习)

引言 大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年10月学习赛的AI金融攻防赛学习总结文档。在前一篇文章中&#xff0c;我们详细介绍了如何在金融场景凭证篡改检测中应用YOLO算法。本文将在此基础…

深入了解Spring重试组件spring-retry

在我们的项目中&#xff0c;为了提高程序的健壮性&#xff0c;很多时候都需要有重试机制进行兜底&#xff0c;最多就场景就比如调用远程的服务&#xff0c;调用中间件服务等&#xff0c;因为网络是不稳定的&#xff0c;所以在进行远程调用的时候偶尔会产生超时的异常&#xff0…

渗透测试实战—教育攻防演练中突破网络隔离

免责声明&#xff1a;文章来源于真实渗透测试&#xff0c;已获得授权&#xff0c;且关键信息已经打码处理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本…

3.matplotlib基础及用法(全)

一.基础绘图 折线图plot散点图scatter柱状图bar饼图pie 二.图表设置 设置标题设置线条设置坐标轴添加图例添加注释设置画布大小与分辨率 三.高级功能 绘制子图保存图形 一.基础绘图 1.折线图plot import matplotlib.pyplot as plt x [1, 2, 3, 4, 5] y [2, 3, 5, 7, 11] pl…

如何选择合适的电感器来匹配感性负载?

在匹配感性负载时&#xff0c;选择合适的电感器是至关重要的。电感器的主要作用是抑制电流变化&#xff0c;从而维持电路的稳定性。为了确保电路的稳定运行&#xff0c;需要考虑以下因素&#xff1a; 1. 电流和电压&#xff1a;首先&#xff0c;需要确定电感器的额定电流和额定…

GJS-WCP

不懂的就问&#xff0c;但我也是二把手......哭死 web GJS-ezssti 很常规的ssti模板注入&#xff0c;只过滤了"/","flag"。 过滤了/,flag 可以利用bash的特性绕过&#xff0c;如字符串截取&#xff0c;环境变量等等。payload1: {{url_for.__globals__[…