【C++】 类和对象 (下)

news2025/6/9 20:06:17

文章目录

  • 📕再谈构造函数
    • 1. 构造函数体赋值
    • 2. 初始化列表
    • 3. explicit 关键字
  • 📕static 成员
    • 1. 概念
    • 2. static 成员变量
    • 3. static 成员函数
  • 📕 友元
    • 1. 友元函数
    • 2. 友元类
  • 📕内部类
  • 📕编译器优化


📕再谈构造函数

1. 构造函数体赋值

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。

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

虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对 对象中 成员变量 的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值

对于上面普通的成员变量,不初始化当然没有关系,但是比如下面的呢?

main 函数中 定义了一个 aa 对象,这是对这个对象的定义,并没有定义其内部的成员变量。
引用、const修饰的成员变量、无默认构造的自定义类型成员。(默认构造:无参、全缺省、编译器自动生成的构造函数) 对于这三类成员变量,前两个都是要在定义的地方初始化,第三个无法传参。所以,必须要有一个 将成员变量初始化 的途径。

对于前两者,当然可以考虑使用缺省值,但是,缺省值是在 C++ 11 才出现的,那么之前是怎么解决的呢?
C++ 使用初始化列表,来完成该功能。

class B
{
public:

	B(int n)
		:_b(0)
	{
		cout << "B()" << endl;
	}


private:
	int _b;
};

class A
{
public:


private:
	int _a1=1; // 声明
	int _a2=2;

	// 引用 、const修饰 、没有默认构造 的  自定义类型成员
	const int _x;
	int& _ref;   
	B bb;
};

int main()
{
	const int t = 10;  // const 修饰,只能初始化的时候给值
	A aa;  // 对象的整体定义,每个成员什么时候定义呢?
	return 0;
}

2. 初始化列表

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

如下,A 中给出了初始化列表,可以简单的理解为在构造函数中间加一点"东西"。

按照初始化列表里面从上到下的顺序来看就是:初始化 _x 为 1 、初始化 _ref 为 _a 的引用 、初始化bb 并且传参为 4(自定义类型,调用它的初始化列表)。
然后函数体里面进行 _a1++ 、 _a2-- 操作。

class B
{
public:

	B(int n)
		:_b(0)
	{
		cout << "B()" << endl;
	}

private:
	int _b;
};

class A
{
public:
	A()
		:_x(1)
		, _ref(_a1)  // 初始化成对 _a1 的引用
		, bb(4)      // B 类的初始化列表有参数,没有默认构造(无参数),需要传参,必须这样写
	{
		_a1++;
		_a2--;
	}
private:
	int _a1=1; // 声明
	int _a2=2;

	// 引用 、const修饰 、没有默认构造 的  自定义类型成员
	const int _x;
	int& _ref;   // 引用也要在定义的地方初始化
	B bb;
};

int main()
{
	const int t = 10;  // const 修饰
	A aa;  // 对象的整体定义

	return 0;
}

成员在初始化列表中的顺序,并不就是它们的初始化顺序。

如下代码,运行结果是:输出 1 随机值 。
因为初始化列表里面,初始化顺序是 声明的顺序,而 不是 初始化列表里面的顺序。(如果是按照初始化列表里的顺序,那么 _a1 先初始化为参数的值,_a2 再初始化为 _a1 的值)

class A
{
public:
	A(int a)
		:_a1(a)
		, _a2(_a1)
	{}
	void Print() {
		cout << _a1 << " " << _a2 << endl;
	}
private:
	int _a2;
	int _a1;
};
int main() {
	A aa(1);
	aa.Print();
}

所以,初始化列表有以下的一些注意点:

    1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)。
    1. 类中包含以下成员,必须放在初始化列表位置进行初始化:
    • 引用 成员变量
    • const 成员变量
    • 自定义类型成员(且该类没有默认构造函数时)
    1. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
    1. 成员变量在类中声明的次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。

我们再来体会一下单参数和多参数的区别。

引用 那一篇文章有写到,内置类型 转换成 自定义类型的引用,必须要用 const 修饰,因为是先将内置类型 放到 临时变量里面,而临时变量具有常性,所以为了避免权限放大,要用 const 修饰。比如下面 main 函数里的第一行代码。

但是对于单个参数的构造函数而言,如果也像下面注释一样,先 构造 临时变量、再将 临时变量 拷贝构造给 a2,未免过于麻烦,所以有的编译器就会优化,将这两个过程合二为一,直接当成构造,1 就相当于传过去的参数。

如下,根据输出结果,也可以看出没有调用拷贝构造

请添加图片描述

class A {
public:
	A(int a)
		:_a1(a)
	{
		cout << "A(int a)" << endl;
	}

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

private:
	int _a1;
};

int main()
{
    const A& a3 = 1; // 将 1 放到 A 类型的 临时变量里面。临时变量具有常性,所以要const修饰

	// 单个参数
    A a1(1);
	A a2 = 1; // 隐式类型转换, 将 1 当作参数,调用初始化列表,有了 A 类型的临时变量,将临时变量拷贝给 a2
	
	return 0;
}

C++ 一开始是不支持多参数的,后来也支持了,其用法和单参数类似,只不过是使用的时候,要用大的花括号

class A {
public:

	A(int a,int b)
		:_a1(a)
	{
		cout << "A(int a)" << endl;
	}


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

private:
	int _a1;
};

int main()
{
	// 多个参数
	A b1(1, 2);
	A b2 = { 2,2 };  // 多参数这样写
	const A& b3 = { 4,7 };

	return 0;
}

3. explicit 关键字

构造函数不仅可以构造 初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值
的构造函数,还具有类型转换的作用,从上面两段代码也可以看出来(将 内置类型转换成了自定义类型)。

但是,如果我们不需要构造函数的类型转换功能,也是可以的,只要用 explicit 修饰构造函数即可。

如下,explicit 修饰之后,依然强制类型转换,会报错。


class A {
public:

	explicit A(int a)
		:_a1(a)
	{
		cout << "A(int a)" << endl;
	}

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

private:
	int _a1;
};

int main()
{
	// 如果不想让内置类型,转换为自定义类型,可以在初始化列表的函数前面用 explicit 修饰
	A a = 1;  // 报错

	return 0;
}

📕static 成员

1. 概念

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数
静态成员变量一定要在类外进行初始化


2. static 成员变量

如果要 实现一个类A,计算程序中实例化了多少个A类型的对象
最先想到的就是,在全局设置一个变量,每一次 构造 或者 拷贝 的时候,该变量的值都 +1 ,这样就可以计算实例化出了多少个对象。

但是,有了 static 成员的知识储备,就可以在类里面实现,这样子能更好地体现“封装”的性质。

如下代码,static 修饰的成员变量 count,不属于某个具体的对象,而是属于整个类。在类里面只是声明,并不是定义,并且在类外定义的时候,是不要加 static 的。
但是如果成员变量在类里面被 private 修饰,那么就不可以访问到。所以必须要用 public 修饰,但是用 public 修饰之后,又可以被任意访问修改。

这样子就又出现了一个问题,如何才可以 不用public 修饰成员变量的情况下,还可以访问到count呢?这里要用static成员函数解决。

class A {
public:

	A(int a)
		:_a1(a)
	{
		count++;
		cout << "A(int a)" << endl;
	}

	A(const A& a)
	{
		count++;
		cout << "A(const A& a)" << endl;
	}

	static int Size()  // 静态成员函数,没有 this 指针,所以无法访问非静态的成员变量
	{
		return count;
	}

public:
	int _a1;
	static int count; // 声明。此外,这个成员变量不属于某个对象,属于整个类
};

int A::count=0;  // 初始化

int main()
{
	// count 需要变成 public 才可以被外部访问到
	A aa(2);
	cout << aa.count << endl;
	cout << A::count << endl;
	
	return 0;
}

3. static 成员函数

static 修饰的成员函数,没有 this 指针。所以,该函数内部不可以对 类 里面的非静态成员变量进行访问

如下,static 修饰的 Size() 函数,只能访问静态成员变量 count ,不可以访问非静态成员变量 _a1 ,因为该函数的参数是没有 this 指针的。
从某种程度上来说,静态成员函数就是为了静态成员变量而创造的。

下面的代码,通过 Size() 函数 返回 count 的值,但是却不会对 count 进行任何修改(因为返回值是拷贝进临时变量的)。所以是最完美的结果,“封装”性体现的很好。

class A {
public:

	A(int a)
		:_a1(a)
	{
		count++;
		cout << "A(int a)" << endl;
	}

	A(const A& a)
	{
		count++;
		cout << "A(const A& a)" << endl;
	}

	static int Size()  // 静态成员函数,没有 this 指针,所以无法访问非静态的成员变量
	{
		return count;
	}

private:
	int _a1;
	static int count; // 声明。此外,这个成员变量不属于某个对象,属于整个类
};

int A::count=0;  // 初始化

int main()
{
	// 定义静态成员函数,这个函数返回 count 的值
	cout << A::Size() << endl;

	cout << A(1).Size() << endl;  // 匿名对象,生命周期只在这一行

	return 0;
}


static 成员的一些特性:

  1. 静态成员所有类对象所共享,不属于某个具体的对象,存放在静态区。
  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。
  3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问。
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员。
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制。

📕 友元

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

1. 友元函数

如下代码,当我们想要在一个类里面对流输出进行重载的时候,使用起来 是 d1<< cout; 和常规使用方式反了。所以,要么在iostream 标准库里面添加重载,要么在外部写流输出重载,前者显然不现实。但是,在类的外部写流输出重载的时候,无法访问类的成员变量,也就无法输出对应的值。

此时就需要友元函数的介入。

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

// d1 << cout;     ->     d1.operator<<(&d1, cout); 不符合常规调用
// 因为成员函数第一个参数一定是隐藏的this,所以d1必须放在<<的左侧
	ostream& operator<<(ostream& _cout)
	{
		_cout << _year << "-" << _month << "-" << _day << endl;
		return _cout;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
    Date d1(2023,2,8);
    d1<<cout;
}

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

如下代码,在 Date 类里面 申明 流输入重载、流输出重载,同时在两个函数的前面都加上 friend 。就代表这两个函数,是 Date 类的友元函数,可以访问 Date 类里面的成员变量

两个函数的函数定义里面也可以看出来,传入的第二个参数是 d 的引用,但是 Date 类里面,成员变量都是 private 修饰的,那么即使是实例化的对象,也无法访问。但是由于两个函数都是Date类的友元函数,所以可以直接访问

class Date {
	friend ostream& operator<<(ostream& _cout, const Date& d);
	friend istream& operator>>(istream& _cin, Date& d);
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};

ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << "-" << d._month << "-" << d._day;
	return _cout;
}
istream& operator>>(istream& _cin, Date& d)
{
	_cin >> d._year;
	_cin >> d._month;
	_cin >> d._day;
	return _cin;
}

int main()
{
	Date d;
	cin >> d;
	cout << d << endl;
	return 0;
}

友元函数的一些性质:

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

2. 友元类

联想友元函数的声明以及用法,友元类也差不多。友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

如下,在 Time 类里面声明,Date 类是 Time 类的友元类,那么 Date 类里面的任何一个成员函数,都可以直接访问 Time 类里面的成员变量

但是,这样的关系是单向的—— Time 类 里面的成员函数,不可以直接访问 Date 类的成员变量。

class Time {
	friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类
	中的私有成员变量
public:
	Time(int hour = 0, int minute = 0, int second = 0)
		: _hour(hour)
		, _minute(minute)
		, _second(second)
	{}
private:
	int _hour;
	int _minute;
	int _second;
};

class Date {
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
	void SetTimeOfDate(int hour, int minute, int second)
	{
// 直接访问 Time 类私有的成员变量
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};

关于友元类的一些性质:

  • 友元关系是单向的,不具有交换性。
    比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接
    访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
  • 友元关系不能传递
    如果C是B的友元, B是A的友元,则不能说明C时A的友元。

📕内部类

如果一个类定义在另一个类的内部,这个在内部的类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。
内部类其实就是外部类的友元类,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。

比如下方的例子,B类在A类的内部,是A类的内部类。所以,B天生就是A的友元类,函数中可以通过A类的对象访问A类的成员变量(比如 foo 函数种,通过 a 访问 h) 。
另外,下方输出结果,sizeof(aa),结果是 8,并没有计算类型B里面的成员变量。这是因为,虽然B是A的内部类,但两个类是独立的,仅仅相当于B被隐藏起来了而已。

class A {
private:
	static int k;
	int h;
public:
	class B { // B天生就是A的友元
	public:
		void foo(const A& a)
		{
			cout << k << endl;//OK
			cout << a.h << endl;//OK
		}
	};
	privateint _b1;
	double _b2;
};

int A::k = 1;

int main()
{
	A::B b;
	b.foo(A());
	A aa;
	cout<<sizeof(aa)<<endl;
	return 0;
}

使用内部类的情况也不多,下面是它的特性:

  1. 内部类可以定义在外部类的public、protected、private都是可以的。
  2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
  3. sizeof(外部类)=外部类,和内部类没有任何关系。

📕编译器优化

在函数传参和传返回值的过程中,一般编译器会做一些优化,减少对象的拷贝,这个在一些场景下还是非常有用的。

如下代码,在构造函数、拷贝构造、赋值重载、析构 这些函数体里面,都使用了流输出,只要调用函数,就会打印相应的内容,调试就可以知道某一行代码具体干了什么

如下,将内置类型的 1 强制转换成A 类型的 aa1,按照之前理解的,要先构造为临时变量,然后临时变量拷贝构造给 aa1 。但是编译器会优化成直接构造,1 就是传的参数。

func(aa1) 要将实参拷贝为形参,所以调用一次拷贝构造。

func1(2); 先将 2 强制类型转换成 A 类型的临时变量,再将临时变量拷贝构造为形参。所以要先构造,再拷贝,但是编译器优化为直接构造。
func1(A(3)); 先以3为参数进行构造成为实参,再拷贝构造传给形参。优化为直接构造。

fuc2() 测试的是传引用,由于传引用不存在把实参拷贝构造给形参,所以没有优化的空间。

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

	A(const A& aa)
		:_a(aa._a)
	{
		cout << "A(const A& aa)" << endl;
	}

	A& operator=(const A& aa)
	{
		cout << "A& operator=(const A& aa)" << endl;

		if (this != &aa) {
			_a = aa._a;
		}

		return *this;
	}

	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};

void func1(A aa)
{

}

void func2(const A& aa)
{

}

int main()
{
	A aa1 = 1;     // 构造+拷贝构造 -》 优化为直接构造
	func1(aa1);    // 无优化
	func1(2);      // 构造+拷贝构造 -》 优化为直接构造
	func1(A(3));   // 构造+拷贝构造 -》 优化为直接构造

	cout << "----------------------------------" << endl;

	func2(aa1);  // 无优化
	func2(2);    // 无优化
	func2(A(3)); // 无优化
	return 0;
}

如下,A 依然是上面的类,一摸一样。改变的是两个外部函数,返回值传A类型的,并且函数内部定义A类型的对象。

直接调用 fuc3() ,无疑,先构造 aa ,再拷贝构造出一个临时变量作为返回值。所以调用了构造、拷贝构造。但是没有优化的空间,因为 func3() 函数内部 aa的 定义 和 返回是分开的

A aa1=func3(); 调用 fun3 的过程和上面一样,先构造、再拷贝构造。生成的临时变量再拷贝构造给 aa1 ,所以经历了两次拷贝构造,此时就会被优化成一个拷贝构造。

但是,对于 aa2 而言,aa2 已经定义好了,aa2 = func3(); 是赋值重载,而不是拷贝构造,所以无法优化。

对于 func4(); 它直接构造出一个匿名对象返回,相当于构造和拷贝构造是连续的,所以可以优化为构造。
A aa3 = func4(); 除了调用 func4() ,还多了将 func4() 生成的临时变量,拷贝构造给 aa3 的过程,所以是 构造、拷贝构造、拷贝构造。编译器会优化成 构造。

A func3()
{
	A aa;
	return aa;   // 不可以优化,因为分开的
}

A func4()
{
	return A();  // 可以优化
}

int main()
{
	func3();

	A aa1 = func3(); // 拷贝构造+拷贝构造  -- 优化为一个拷贝构造


	cout << "****" << endl;

	A aa2;
	aa2 = func3();   // 不能优化  , 因为是赋值重载


	cout << "---------------------------" << endl;

	func4();         // 构造+拷贝构造 -- 优化为构造
	A aa3 = func4(); // 构造+拷贝构造+拷贝构造  -- 优化为构造

	return 0;
}

上面所提到的一些优化,对于A类而言,确实没有什么区别,但是如果对于二叉树那些的呢?多次拷贝开销很大,所以,要学会使用这些小技巧,让程序更加优质!

这里浅浅地总结一下:

  • 如果可以,尽量 return 匿名对象
  • 函数传参,尽量传引用
  • 如果要用一个对象来初始化另一个对象,尽量使用拷贝构造而不是赋值重载。

类和对象部分到这一篇文章就算是完结啦!有什么错误的地方欢迎指正!!

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

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

相关文章

Python traceback模块:获取异常信息

除了使用 sys.exc_info() 方法获取更多的异常信息之外&#xff0c;还可以使用 traceback 模块&#xff0c;该模块可以用来查看异常的传播轨迹&#xff0c;追踪异常触发的源头。下面示例显示了如何显示异常传播轨迹&#xff1a;classSelfException(Exception): pass defmain(): …

linux 学习(持续更新)

一&#xff1a;初识linux 新装操作环境&#xff1a; mac intel电脑 CentOS系统版本&#xff1a;CentOS-8.1.1911 在这里解释一下[chenllocalhost /]$这句话的含义&#xff1a; chenl是用户名&#xff0c;也就是你自己起的名字。 是分割的符号 localhost是主机名&#xff0c;也…

轻松实现微信小程序上传多文件/图片到腾讯云对象存储COS(免费额度)

概述 对象存储&#xff08;Cloud Object Storage&#xff0c;COS&#xff09;是腾讯云提供的一种存储海量文件的分布式存储服务&#xff0c;用户可通过网络随时存储和查看数据。个人账户首次开通COS可以免费领取50GB 标准存储容量包6个月&#xff08;180天&#xff09;的额度。…

VBA提高篇_19 可选参数Optional_ IsMissing _MSgbox

文章目录1. 可选参数Optional2.IsMissing判断参数是否提供,只能判断变体类型3. 使用 : 可以按参数名传递参数 a:1,c:34.Msgbox 常用参数5.VBA颜色常量表1. 可选参数Optional Optional 代表本参数是可选项 False ; 代表参数若不指定,则默认为False Function mySumProduct(r As R…

2023年rabbitMq面试题汇总3(5道)

一、如何确保消息不丢失&#xff1f;消息持久化的前提是&#xff1a;将交换器/队列的durable属性设置为true&#xff0c;表示交换器/队列是持久交换器/队列&#xff0c;在服务器崩溃或重启之后不需要重新创建交换器/队列&#xff08;交换器/队列会⾃动创建&#xff09;。如果消…

【监控】Prometheus(普罗米修斯)监控概述

文章目录一、监控系统概论二、基础资源监控2.1、网络监控2.2、存储监控2.3、服务器监控2.4、中间件监控2.5、应用程序监控&#xff08;APM&#xff09;三、Prometheus 简介3.1、什么是 Prometheus3.2、优点3.3、组件3.4、架构3.5、适用于什么场景3.6、不适合什么场景四、数据模…

weston 2: 登录后直接启动weston配置

本人Kubuntu版本是22.04 名词&#xff1a;SDDM&#xff08;SDDM - Arch Linux 中文维基&#xff09;显示管理器 配置流程如下&#xff1a; 1.修改配置文件 a.配置.bashrc vim ~/.bashrc //以下内容删除 #export WLD$HOME/install #export LD_LIBRARY_PATH$WLD/lib/x86_64-…

使用IntelliJ IDEA搭建datax-web开发环境

记录&#xff1a;372场景&#xff1a;使用IntelliJ IDEA搭建datax-web开发环境&#xff0c;以及datax-web基本使用。版本&#xff1a;JDK 1.8Python 2.7.5datax-web开源地址&#xff1a;https://github.com/WeiYe-Jing/datax-web1.配置Maven环境1.1安装目录目录&#xff1a;D:\…

Spring6-基于XML自动装配

一、介绍自动装配&#xff1a;根据指定的策略&#xff0c;在IOC容器中匹配某一个bean&#xff0c;自动为指定的bean中所依赖的类类型或接口类型属性赋值二、创建controllerpackage com.wsy.auto.controller;import com.wsy.auto.service.UserService; import com.wsy.auto.serv…

应用于LSSVM对偶问题的张量列车卡尔曼滤波器的代码(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 ​ &#x1f4a5;1 概述 支持向量机是借助优化方法解决机器学习问题的新工具.近年来,支持向量机越来越受到人们的广泛关注,在其理论研究和算法实现方…

Vue拼图验证

vue-puzzle-verification 封装的一个用于登录验证的拼图的vue组件&#xff0c;使用了canvas画图和拖拽的一些技巧。支持大小、形状、图片、偏差、范围的自定义。 一、安装使用 npm install vue-puzzle-verification 二、main.js里引入 import PuzzleVerification from vue…

训练营day18

513.找树左下角的值 力扣题目链接(opens new window) 给定一个二叉树&#xff0c;在树的最后一行找到最左边的值。 示例 1: 示例 2: var findBottomLeftValue function(root) {let queue [root];let res root.val;while (queue.length) {let node queue.shift();if (nod…

Blender——烘培记录

参考链接&#xff1a;Blender2.8基础三&#xff1a;贴图烘培篇Blender 材质如何导出到 UE 和 Unity 里使用贴图烘焙打开【渲染属性】面板&#xff0c;把【渲染引擎】改为【Cycles】。把【设备】改为GPU计算&#xff0c;可以加快烘培速度。创建一个【图像纹理】节点&#xff08;…

fastadmin后台表单文字过长,限制显示,鼠标悬停显示全部

问题&#xff1a;显示文字区域过长&#xff0c;影响用户体验感 解决措施&#xff1a; 特别注意&#xff1a; return "<span styledisplay: block;overflow: hidden;text-overflow: ellipsis;white-space: nowrap; title" row.contents ">" value …

ARM uboot源码分析1-启动第一阶段

一、start.S 引入 1、u-boot.lds 中找到 start.S 入口 (1) 在 C 语言中整个项目的入口就是 main 函数&#xff08;这是 C 语言规定的&#xff09;&#xff0c;所以譬如说一个有 10000 个.c 文件的项目&#xff0c;第一个要分析的文件就是包含了 main 函数的那个文件。 (2) 在…

分享75个JS焦点图代码,总有一款适合您

分享75个JS焦点图代码&#xff0c;总有一款适合您 75个JS焦点图代码下载链接&#xff1a;https://pan.baidu.com/s/1WuydBKN3eYd3H64lPXv0Fw?pwd0nq7 提取码&#xff1a;0nq7 Python采集代码下载链接&#xff1a;https://wwgn.lanzoul.com/iKGwb0kye3wj base_url "…

MySQL面试题:关系型数据库SQL和非关系型数据库NoSQL

文章目录一、四大非关系型数据库与关系型数据库的对比1. 关系型数据库2. 基于列的数据库3. 键值对存储4. 文档存储5. 图形数据库参考文章&#xff08;金文&#xff09;&#xff1a;四大非关系型数据库类型&#xff0c;你知道多少 参考文章&#xff1a;“行式存储”和“列式存储…

2022虎符CTF-WEB赛后复现

1、ezphp 参考Jacko师傅的这篇虎符CTF 写的已经很详细了&#xff0c;先简单梳理一下题目&#xff0c;题目与P师傅的这篇文章类似我是如何利用环境变量注入执行任意命令。简单来说就是不同的系统&#xff0c;他的system命令调用的命令不同。 php中调用system本质上是调用了sh…

UDP报文结构

UDP协议 基本特点&#xff1a;无连接、不可靠传输、面向数据报、全双工 UDP协议报文结构 &#xff0c;以下分别是种画法 对上图进行解释&#xff1a; UDP就会把载荷数据&#xff08;就通过UDP socket ,也就是send方法拿来的数据&#xff0c;基础上再在前面拼接上几个字节的…

appium ios真机自动化环境搭建运行(送源码)

appium ios真机自动化环境搭建&运行&#xff08;送源码&#xff09; 目录&#xff1a;导读 &#xff08;1&#xff09;安装JDK&#xff0c;并配置环境变量&#xff0c;方法如下&#xff1a; &#xff08;2&#xff09;安装Xcode、Xcode commandline tools和iOS模拟器 &…