【C++】类和对象——Lesson2

news2025/1/15 23:03:31

Hi~!这里是奋斗的小羊,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~
💥💥个人主页:奋斗的小羊
💥💥所属专栏:C++

🚀本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为记录我的学习过程及理解。文笔、排版拙劣,望见谅。


目录

  • 1、赋值运算符重载
    • 1.1运算符重载
    • 1.2赋值运算符重载
  • 2、取地址运算符重载
    • 2.1const成员函数
    • 2.2取地址运算符重载
  • 3、类型转化
  • 4、再探构造函数
  • 5、static成员
  • 6、友元
  • 7、内部类
  • 8、匿名对象

1、赋值运算符重载

1.1运算符重载

当运算符被用于类类型的对象时,C++允许我们通过运算符重载的形式指定新的定义。C++规定类类型对象使用运算符时,必须转换成调用对应运算符重载,若没有对应的运算符重载,则会编译报错。

  • 运算符重载是具有特殊名字的函数,它的名字是由operator和后面要定义的运算符共同构成,和其他函数一样,它也具有其返回类型和参数列表以及函数体
  • 重载运算符函数的参数个数和该运算符作用的运算对象数量一样多。一元运算符有一个参数,二元运算符有两个参数,二元运算符的左侧运算对象传给第一个参数,右侧运算对象传给第二个参数
#include <iostream>
using namespace std;

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

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

	//类中成员变量都可以访问
	//int Get()
	//{
	//	return _year;
	//}

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

bool operator<(Date d1, Date d2)
{
	return d1._year < d2._year
		&& d1._month < d2._month
		&& d1._day < d2._day;
}

int main()
{
	Date x(2024, 7, 28);
	Date y(2004, 11, 7);
	operator<(x, y);//这样写和普通函数没什么区别
	//可以像下面这样调用,和上面一样
	x < y;
	return 0;
}

请添加图片描述

  • 如果一个重载运算符函数是成员函数,则它的第一个运算对象默认传给隐式的this指针,因此运算符重载作为成员函数时,参数比运算对象少一个
#include <iostream>
using namespace std;

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

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

	//类中成员变量都可以访问
	//int Get()
	//{
	//	return _year;
	//}

	bool operator<(Date d2)
	{
		return _year < d2._year
			&& _month < d2._month
			&& _day < d2._day;
	}

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

int main()
{
	Date x(2024, 7, 28);
	Date y(2004, 11, 7);

	//operator<(x, y);//这样写和普通函数没什么区别
	//可以像下面这样调用,和上面一样
	//x < y;

	//x传给this指针,y传给d2
	x.operator<(y);
	x < y;

	return 0;
}
  • 运算符重载后,其优先级和结合性与对应的内置类型运算符保持一致
  • 不能通过连接语法中没有的符号来创造新的操作符,比如operator@
  • .* :: sizeof ?: . 以上5个运算符不能重载
  • 重载操作符至少有一个类类型参数,不能通过运算符重载改变内置类型对象的含义,如:int operator+(int x, int y);
  • 一个类需要重载哪些运算符,是看哪些运算符重载后有意义,比如Date类重载operator-就有意义,但是重载operator+就没有意义
  • 重载++运算符时,有前置++和后置++,运算符重载函数名都是operator++,无法很好的区分。C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,方便区分
  • 重载<<和>>时,需要重载为全局函数,因为重载为成员函数,this指针默认抢占了第一个形参位置,第⼀个形参位置是左侧运算对象,调⽤时就变成了 对象<<cout,不符合使⽤习惯和可读性。重载为全局函数把ostream/istream放到第⼀个形参位置就可以了,第⼆个形参位置当类类型对象

1.2赋值运算符重载

赋值运算符重载是一个默认成员函数,用于完成两个已经存在的对象之间的拷贝赋值,这里要注意跟拷贝构造区分,拷贝构造用于一个对象拷贝初始化给另一个要创建的对象。

int main()
{
	Date d1(2024, 7, 29);
	Date d2(2004, 11, 7);

	//赋值重载
	d1 = d2;

	//拷贝构造
	Date d3(d2);
	Date d4 = d2;

	return 0;
}

赋值运算符重载的特点:

  1. 赋值运算符重载是一个运算符重载规定必须重载为成员函数。赋值运算符重载的参数建议写成const当前类类型引用,传值传参会有拷贝
//d1 = d2;
void operator=(Date d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}

如果这样写,因为赋值前要传参,所以会先调用拷贝构造,再调用复制重载。

  1. 有返回值,且建议写成当前类类型引用(因为传值返回也会先拷贝),引用返回可以提高效率,有返回值目的是为了支持连续赋值场景
  2. 没有显示实现时,编译器会自动生成一个默认赋值运算符重载,默认赋值运算符重载行为跟默认拷贝构造函数类似,对内置类型成员变量会完成值拷贝 / 浅拷贝(一个字节一个字节的拷贝),对自定义类型成员变量会调用它的赋值重载
  3. Date这样的类成员变量全是内置类型且没有指向什么资源,编译器自动生成的赋值运算符重载就可以完成需要的拷贝,所以不需要我们显示实现赋值重载。像Stack这样的类,虽然也都是内置类型,但是_a指向了资源,编译器自动生成的赋值重载完成的值拷贝 / 浅拷贝不符合我们的需求,所以需要我们自己实现深拷贝(对指向的资源也进行拷贝)。像MyQueue这样的类型内部主要是自定义类型Stack成员,编译器自动生成的赋值重载会调用Stack的赋值重载,也不需要我们显示实现MyQueue的赋值运算符重载。如果一个类显示实现了析构并释放资源,那么它就需要显示写赋值重载,否则不需要
#include <iostream>
using namespace std;

class Date
{
public:
	//构造
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	//拷贝构造
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	//赋值运算符重载
	//d1 = d2;
	Date& operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;
	}
	
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2024, 7, 29);
	Date d2(2004, 11, 7);

	//赋值重载
	d1 = d2;

	//拷贝构造
	Date d3(d2);
	Date d4 = d2;

	return 0;
}

2、取地址运算符重载

2.1const成员函数

  • const修饰的成员函数称之为const成员函数,const修饰成员函数放到成员函数参数列表的后面
  • const实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。const修饰Date类的Print成员函数,Print隐含的this指针由Date* const this变为const Date* const this
#include <iostream>
using namespace std;

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

	//void Print(const Date* const this)
	void Print() const
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

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

int main()
{
	//const限定d1不能被修改
	const Date d1(2024, 7, 30);//权限平移
	d1.Print();

	Date d2(2024, 8, 1);//权限缩小
	d2.Print();
	return 0;
}

2.2取地址运算符重载

取地址运算符重载分为普通取地址运算符重载和const取地址运算符重载,一般这两个函数编译器自动生成的就够我们用了,不需要去显示实现,除非一些特殊的场景,比如我们不想让别人取到当前类对象的地址,就可以自己实现一份,胡乱返回一个地址。

class Date
{
public:
	Date* operator&()
	{
		//正常代码
		//return this;
		return (Date*)0x004FF88C;
	}
	
	const Date* operator&() const
	{
		//return this;
		return (Date*)0x004FF88C;
	}

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

3、类型转化

  • C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数
  • 构造函数前加explicit就不再支持隐式类型转换
#include <iostream>
using namespace std;

class A
{
public:
	//explicit A(int a)
	A(int a = 1)
	{
		_a1 = a;
	}

	A(int a1, int a2)
	{
		_a1 = a1;
		_a2 = a2;
	}

	A(const A& aa)
	{
		_a1 = aa._a1;
	}

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

class Stack
{
public:
	//临时变量具有常性,用const修饰
	void Push(const A& aa)
	{
		//...
	}
private:
	A _arr[20];
	int _top;
};

int main()
{
	A aa1 = 1;
	aa1.Print();
	
	//隐式类型转换
	//构造一个A的临时对象,再用这个临时对象拷贝构造aa2
	//编译器遇到连续构造+拷贝构造->优化为直接构造
	A aa2 = 2;
	aa2.Print();

	A& raa1 = aa2;
	const A& raa2 = 2;//临时变量具有常性

	Stack st;
	A aa3 = 3;
	st.Push(aa3);//构造一个A类对象再插入

	st.Push(3);//直接插入

	A aa4 = { 4, 5 };
	const A& aa5 = { 4, 5 };
	st.Push(aa4);
	st.Push({ 4, 5 });

	return 0;
}

4、再探构造函数

之前我们实现构造函数时,初始化成员变量主要是使用函数体内赋值,构造函数初始化还有一种方法,就是初始化列表,每个构造函数都有初始化列表。

  • 初始化列表的使用方式是以一个冒号开头,接着是一个以逗号分隔的数据成员列表,每个“成员变量”后面跟一个放在括号中的初始值或表达式
  • 每个成员变量在初始化列表中只能出现一次,语法理解上初始化列表可以认为是每个成员变量定义初始化的地方
  • 引用成员变量、const成员变量,没有默认构造的类类型变量,必须放在初始化列表位置进行初始化,否则会编译报错
  • C++11支持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显示在初始化列表初始化的成员使用的
  • 尽量使用初始化列表初始化,因为那些你不在初始化列表初始化的成员也会走初始化列表,如果这个成员在声明位置给了缺省值,初始化列表会用这个缺省值初始化。如果你没有给缺省值,对于没有显示在初始化列表初始化的内置类型成员是否初始化取决于编译器,C++并没有规定。对于没有显示在初始化列表初始化的自定义类型成员会调用这个成员类型的默认构造函数,如果没有默认构造函数会编译错误
#include <iostream>
using namespace std;

class Time
{
public:
	Time(int hour)
		:_hour(hour)
	{
		cout << "Time()" << endl;
	}
private:
	int _hour;
};

class Date
{
public:
	Date(int& rx, int year = 2024, int month = 1, int day = 1)
		:_year(year)
		,_month(month)
		,_day(day)
		,_n(1)
		,_m(rx)
		,_t(2)
	{
		//...
	}

	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	//这里不是初始化,是缺省值,这个缺省值是给初始化列表的
	//如果初始化列表没有显示初始化,默认就会用这个缺省值初始化
	int _year = 2024;
	int _month = 11;
	int _day = 7;

	//必须在初始化列表初始化
	const int _n = 1;
	int& _m = _day;
	Time _t = 12;//没有默认构造

	int* _ptr = (int*)malloc(4);
};

int main()
{
	int x;
	//对象定义
	Date d1(x, 2024, 7, 31);
	d1.Print();

	//const定义的变量、引用必须在初始化列表定义
	const int x = 1;
	Date& d2 = d1;

	return 0;
}
  • 初始化列表中按照成员变量在类中声明顺序进行初始化,跟成员在初始化列表出现的先后顺序无关,但是建议声明顺序和初始化列表顺序保持一致

| 下面程序的运行结果是什么:

#include <iostream>
using namespace std;

class B
{
public:
	B(int a)
		:_a1(a)
		,_a2(_a1)
	{
		//...
	}

	void Print()
	{
		cout << _a1 << " " << _a2 << endl;
	}
private:
	int _a2 = 2;
	int _a1 = 2;
};

int main()
{
	B b(1);
	b.Print();
	return 0;
}

在这里插入图片描述

因为在B类中,先声明的_a2,再声明的_a1,所以在初始化列表中先初始化_a2,再初始化_a1,初始化_a2的时候_a1还是随机值,然后再用a初始化_a1。


5、static成员

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

求1+2+3+…+n

class Sum
{
public:
	Sum()
	{
		_ret += _i;
		++_i;
	}

	static int GetRet()
	{
		return _ret;
	}

private:
	static int _i;
	static int _ret;
};

int Sum::_i = 1;
int Sum::_ret = 0;

class Solution {
public:
    int Sum_Solution(int n) {
        Sum arr[n];
		return Sum::GetRet();
    }
};

当定义一个Sum类类型长度为n的变长数组时,会调用n次构造,实现n的累加。

| 设已有A、B、C、D四个类定义,程序中A、B、C、D构造函数调用顺序为?析构函数调用顺序为?

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

我们知道对象实例化时自动调用构造函数,a、b、c、d四个对象创建的先后顺序是c、a、b、d,所以构造函数的调用顺序就是C、A、B、D;对象在销毁时自动调用析构函数,又规定后定义的先析构,所以局部对象a和b先析构b再析构a,而d是静态的局部对象,生命周期是全局的,所以再析构d,最后析构c, 所以析构函数的调用顺序就是B、A、D、C。


6、友元

友元提供了一种突破类访问限定符封装的方式,友元分为友元函数友元类,在函数声明或者类声明的前面加friend,并且把友元声明放到一个类里面。

  • 外部友元函数可访问类的私有和保护成员,友元函数仅仅是一种声明,不是类的成员函数
  • 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
  • 友元类中的成员函数都可以是另一个类的友元函数,都可以访问另一个类中的私有和保护成员
  • 友元类的关系是单向的,不具有交换性,比如A类是B类的友元,但是B类不是A类的友元
  • 友元类关系不能传递,如果A是B的友元,B是C的友元,但A不是C的友元
  • 有时提供了便利,但友元会增加耦合度,破坏了封装,所以友元不宜多用
// 前置声明,否则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;
}

7、内部类

如果一个类定义在另一个类的内部,这个内部类就叫做内部类。

  • 内部类是一个独立的类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限制,所以外部类定义的对象中不包括内部类
  • 内部类默认是外部类的友元类
#include<iostream>
using namespace std;

class A
{
public:
	class B // B默认就是A的友元
	{
		public :
		void foo(const A& a)
		{
			cout << _k << endl; //OK
			cout << a._h << endl; //OK
		}
	};
private :
	static int _k;
	int _h = 1;
};

int A::_k = 1;

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

请添加图片描述

  • 内部类本质也是一种分装,当A类跟B类精密关联,A类实现出来主要是给B类使用,那么可以考虑把A类设计为B类的内部类,如果放到private / protected位置,那么A类就是B类的专属内部类,其他地方都用不了

那求1+2+3+…+n这个题我们可以这样写:

class Solution {
public:
	int Sum_Solution(int n) {
		Sum arr[n];
		return _ret;
	}
private:
	//
	class Sum
	{
	public:
		Sum()
		{
			_ret += _i;
			++_i;
		}
	};
	static int _i;
	static int _ret;
};

int Solution::_i = 1;
int Solution::_ret = 0;

8、匿名对象

  • 用类型(实参)定义出来的对象叫匿名对象,相比之前我们定义的类型 对象名(实参)定义出来的叫有名对象
  • 匿名对象生命周期只在当前一行,一般临时定义一个对象当前用一下即可,就可以定义匿名对象
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();
	A(1);
	A aa2(2);

	// 匿名对象在这样场景下就很好⽤,单纯想调用类中的一个函数
	Solution().Sum_Solution(10);

	return 0;
}

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

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

相关文章

最全架构学习路线图,海量大厂架构案例

很多读者经常抱怨&#xff0c;工作中涉及不到太多架构设计&#xff0c;对于架构的理解少之又少。 零散地做过一些架构工作&#xff0c;但完全不知道架构设计的全流程是怎样的。 想要成长为架构师&#xff0c;缺乏系统的方法论指导。 无论是程序员&#xff0c;还是产品经理&a…

数字图像边缘曲率计算及特殊点检测

一、曲率和数字图像边缘曲率检测常用方法简介 边缘曲率作为图像边缘特征的重要参数&#xff0c;不仅反映了边缘的几何形状信息&#xff0c;还对于图像识别、图像分割、目标跟踪等任务具有显著影响。 曲线的曲率&#xff08;curvature&#xff09;就是针对曲线上某个点的切线方向…

只有4%知道的Linux,看了你也能上手Ubuntu桌面系统,Ubuntu简易设置,源更新,root密码,远程服务...

创作不易 只因热爱!! 热衷分享&#xff0c;一起成长! “你的鼓励就是我努力付出的动力” 最近常提的一句话&#xff0c;那就是“但行好事&#xff0c;莫问前程"! 与辉同行的董工说​&#xff1a;​守正出奇。坚持分享&#xff0c;坚持付出&#xff0c;坚持奉献&#xff0c…

患者特征对AI算法在解释阴性筛查数字乳腺断层摄影研究中的表现的影响| 文献速递-AI辅助的放射影像疾病诊断

Title 题目 Patient Characteristics Impact Performance of AI Algorithm in Interpreting Negative Screening Digital Breast Tomosynthesis Studies 患者特征对AI算法在解释阴性筛查数字乳腺断层摄影研究中的表现的影响 Background 背景 Artificial intelligence (AI)…

什么是云边协同?

当今信息技术高速发展的时代&#xff0c;"云边协同"&#xff08;Edge Cloud Collaboration&#xff09;已经成为一个备受关注的话题。它涉及到云计算和边缘计算的结合&#xff0c;为数据处理、存储和应用提供了全新的可能性。本文将介绍云边协同的概念、优势以及在不…

Learning vtkjs之LookUpTable

颜色映射表 LookUpTable 介绍 先看官方的介绍&#xff1a; vtkLookupTable is a 2D widget for manipulating a marker prop vtkLookupTable 是一个用于操纵标记属性的2维的小部件。 一般可以用来进行颜色刻度的显示。它会帮我们进行颜色线性插值计算 代码效果 其实设置一个…

C++必修:STL之vector的了解与使用

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C学习 贝蒂的主页&#xff1a;Betty’s blog 1. C/C中的数组 1.1. C语言中的数组 在 C 语言中&#xff0c;数组是一组相同类型…

顺序消费rocketMQ(FIFO先进先出)和小技巧 取模运算的周期性特征来将数据分组。

20240801 一、顺序消费MQ&#xff08;FIFO先进先出&#xff09;介绍 二、一个小技巧&#xff0c;对于取模运算&#xff0c;用来在几以前进行随机选取&#xff0c;取模运算的周期性特征来将数据分组&#xff0c;使用场景对于取模会重复问题 一、顺序消费MQ&#xff08;FIFO先进先…

openeuler下载docker

https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/rhel/9/x86_64/stable/ #清华的网址 https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable/ #阿里云的网址 开始配置 vim /etc/yum.repos.d/docker-ce.repo #写仓库&#xff0c;我这里…

【初阶数据结构篇】归并排序和计数排序(总结篇)

文章目录 归并排序和计数排序前言代码位置归并排序计数排序排序性能比较排序算法复杂度及稳定性分析 归并排序和计数排序 前言 本篇以排升序为例 代码位置 gitee 前篇&#xff1a;【初阶数据结构篇】冒泡排序和快速排序 中篇&#xff1a;【初阶数据结构篇】插入、希尔、选择…

【Qt】QDateTimeEdit

在Qt中&#xff0c;QDateEdit是用于选择日期的微调框&#xff0c;QTimeEdit是用于选择小时和分钟的微调框 QDateTimeEdit则是基于QDateEdit和QTimeEdit的组合控件&#xff0c;能够同时显示日期和时间&#xff0c;并允许用户以交互方式编辑日期 常用属性 属性说明dateTime时间…

electron-updater实现electron全量更新和增量更新——渲染进程UI部分

同学们可以私信我加入学习群&#xff01; 正文开始 前言更新功能所有文章汇总一、两个同心球效果实现二、球内进度条、logo、粒子元素实现2.1 球内包含几个元素&#xff1a;2.2 随机粒子生成方法generateRandomPoint2.3 创建多个粒子的方法createParticle 三、gsap创建路径动画…

基于python的百度迁徙迁入、迁出数据分析(六)

书接上回&#xff0c;苏州市我选取了2024年5月1日——5月5日迁入、迁出城市前20名并求了均值&#xff0c;从数据中可以看出苏州市与上海市的关系还是很铁的&#xff0c;都互为对方的迁入、迁出的首选且迁徙比例也接近4分之一&#xff0c;名副其实的老铁了&#xff1b; 迁出城市…

Seurat-SCTransform与harmony整合学习续(亚群分析)

目录 提取细胞亚群 SCTransform-harmony技术路线 ①亚群SCTransform标准化 ②harmony去批次 这里对上一章的内容进行补充&#xff1a; Seurat-SCTransform与harmony整合学习-CSDN博客 提取细胞亚群 rm(list ls()) library(Seurat)#好像先后需要先后加载 library(patchw…

【Jenkins】在linux上通过Jenkins编译gitee项目

因项目需求近期在linux服务器上部署了Jenkins来自动编译gitee上的项目源码&#xff0c;期间踩到了一些坑&#xff0c;花费了不少时间来处理&#xff0c;特此记录。 所需资源下载列表&#xff1a; Jenkins &#xff1a;https://mirrors.tuna.tsinghua.edu.cn/jenkins/war/2.46…

文件系统 --- 重定向,缓冲区

序言 本篇文章的内容和上一篇文章 &#x1f449;点击查看 紧密相连&#xff0c;所以为了更好的理解本篇文章&#xff0c;需要大家将前置知识准备好哦&#x1f607;。  本文主要向大家介绍文件的重定向&#xff0c;以及基于用户级别的缓冲区和基于操作系统级别的缓冲区。原来看…

AI技术和大模型对人才市场的影响

012024 AI技术和大模型 2024年AI技术和大模型呈现出多元化和深入融合的趋势&#xff0c;以下是一些关键的技术方向和特点&#xff1a; 1. 生成式AI 生成式AI&#xff08;Generative AI&#xff09;在2024年继续快速发展&#xff0c;它能够创造全新的内容&#xff0c;而不仅仅…

Redis——有序集合

目录 1. 添加元素 ZADD 2. 查看全部元素 ZRANGE 3. 查看某个元素的分数 ZSCORE 4. 查看元素的排名 ZRANK SortedSet 也叫 ZSet ,即有序集合&#xff0c; 有序集合与集合的区别&#xff1a; 有序集合的每个元素都会关联一个浮点类型的分数&#xff0c;依赖该分数的的大小对…

《Milvus Cloud向量数据库指南》——多模态融合新纪元:音频、视频与文本的无缝转换

在探讨多模态数据处理与应用的广阔领域中,多模态文本、音频、视频数据的融合与交互成为了近年来人工智能研究的热点之一。这一趋势不仅推动了技术的深度发展,也为众多行业带来了前所未有的创新机遇。本文将深入剖析多模态文本-音频与多模态文本-视频RAG(Retrieval-Augmented…