C++类与对象基础探秘系列(二)

news2024/11/21 0:26:42

目录

类的6个默认成员函数

构造函数

  构造函数的概念

  构造函数的特性

析构函数

  析构函数的概念

  析构函数的特性

拷贝构造函数

  拷贝构造函数的概念

  拷贝构造函数的特性

赋值运算符重载

  运算符重载

  赋值运算符重载

const成员

  const修饰类的成员函数

取地址及const取地址操作符重载


类的6个默认成员函数

        如果一个类中什么成员都没有,简称为空类。

        空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。

        默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

注意:这些默认成员函数如果未被显式定义,编译器会自动生成。 

构造函数

        构造函数是C++编程语言中一个特殊类型的方法,其主要目的是在创建类的新对象时初始化该对象的成员变量。

  构造函数的概念

        概念:名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有 一个合适的初始值,并且在对象的生命周期内只调用一次。

例如,以下日期类中的成员函数Date就是一个构造函数。当你用该日期类创建一个对象时,编译器会自动调用该构造函数对新创建的变量进行初始化。 

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

注意:构造函数的主要职责是初始化对象不是开辟空间创建对象。 

  构造函数的特性

1、构造函数的函数名与类名相同。

2、构造函数无返回值。

        无返回值是真的无返回值,而不是说返回值为void。

3、对象实例化时编译器自动调用对应的构造函数。

        当用类创建一个对象时,编译器会自动调用该类的构造函数对新创建的变量进行初始化。

4、构造函数支持重载。

       意味着可以有多种初始化对象的方式,编译器会根据所传递的参数去调用对应的构造函数。

class Date
{
public:
	// 1.无参构造函数
	Date()
	{}

	// 2.带参构造函数
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

void TestDate()
{
	Date d1; // 调用无参构造函数
	Date d2(2015, 1, 1); // 调用带参的构造函数
}

注意: 如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明

即 Date d3(); 声明了d3函数,该函数无参,返回一个日期类型的对象

5、无参的构造函数、全缺省的构造函数以及我们不写编译器自动生成的构造函数都称为默认构造函数,并且默认构造函数只能有一个。

        初学C++时,可能认为只有当我们不写,编译器自动生成的构造函数才被称为默认构造函数。其实并不是这样的,以下3种都叫做默认构造函数:

  •         我们不写,编译器自动生成的构造函数。
  •         我们自己写的无参的构造函数。
  •         我们自己写的全缺省的构造函数。

总结:涉及到不接受参数的构造函数,都可以视作“默认构造函数”的范畴。

6、如果类中没有显示定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,若用户显示定义了,则编译器就不再生成。

        那么既然在我们不写的情况下,编译器会自动生成一个构造函数,那我们是不是就没有必要自己写构造函数了?

#include <iostream>

using namespace std;

class Date
{
public:
	void Print()
	{
		cout << _year << "年 " << _month << "月 " << _day << "日 " << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1; // 编译器将调用自动生成的默认构造函数对d1进行初始化
	d1.Print();
	return 0;
}

代码结果:

        d1对象调用了编译器自动生成的构造函数后,d1对象的_year/_month/_day依旧是随机值,那这编译器自动生成的构造函数还有什么意义?

7、编译器生成默认的构造函数会对自定类型成员调用的它的默认成员函数。

编译器自动生成的构造函数机制:
        1、编译器自动生成的构造函数对内置类型不做处理。
        2、对于自定义类型,编译器会再去调用它们自己的默认构造函数。

        C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int/char...,自定义类型就是我们使用class/struct/union等自己定义的类型。看看下面的程序

#include <iostream>

using namespace std;

class Time
{
public:
	Time()
	{
		cout << "Time()" << endl; // 查看是否进入该构造函数
		_hour = 0;
		_minute = 0;
		_second = 0;
	}
private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{
private:
	// 基本类型(内置类型)
	int _year;
	int _month;
	int _day;
	// 自定义类型
	Time _t;
};

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

代码结果:

 总结:尽管C++编译器会自动生成默认构造函数,但往往我们需自定义构造函数达到我们想要的效果

析构函数

  析构函数的概念

        概念:与构造函数功能相反,析构函数负责完成对象的销毁,对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。

        我们知道当一个类对象销毁时,其中的局部变量也会随着该对象的销毁而销毁,例如,我们用日期类创建了一个对象d1,当d1被销毁时,对象d1当中的局部变量_year/_month/_day也会被编译器销毁。

        但是这并不意味着析构函数没有什么意义。像栈(Stack)这样的类对象,当该对象被销毁时,其中动态开辟的栈并不会随之被销毁,需要我们对其进行空间释放,这时析构函数的意义就体现了。

  析构函数的特性

1. 析构函数名是在类名前加上字符 ~。

class Date
{
public:
	Date() // 构造函数
	{}
	~Date() // 析构函数
	{}
private:
	int _year;
	int _month;
	int _day;
};

2. 无参数无返回值类型。

        无返回值也是真的无返回值,而不是返回值为void。

3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。

        析构函数不能重载。

4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

#include <iostream>

using namespace std;

class MyClass {
public:
    // 构造函数
    MyClass() {
        cout << "构造函数被调用,对象创建了。" << endl;
    }

    // 析构函数
    ~MyClass() {
        cout << "析构函数被调用,对象将被销毁。" << endl;
    }
};

int main() 
{
    // 创建一个MyClass类型的局部对象
    MyClass obj;
    // 当obj的作用域结束时(这里是大括号结束),析构函数会被自动调用
    // 这里obj对象生命周期结束,析构函数被调用
    return 0;
}

代码结果:

5. 关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器生成的默认析构函数,对自定义类型成员调用它的析构函数。

#include <iostream>

using namespace std;

// 自定义类,包含一个构造函数和析构函数
class CustomClass 
{
public:
    CustomClass() 
    {
        cout << "CustomClass 的构造函数被调用。" << endl;
    }
    
    ~CustomClass() 
    {
        cout << "CustomClass 的析构函数被调用。" << endl;
    }
};

// 另一个类,包含CustomClass类型的成员变量
class AnotherClass 
{
private:
    CustomClass myCustomObject; // 自定义类型成员变量

public:
    // 缺少显式定义的构造函数和析构函数,
    // 编译器会自动生成默认的构造函数和析构函数
};

int main() 
{
    AnotherClass obj; // 创建AnotherClass类型的对象obj
    // 当obj的作用域结束时(这里是大括号结束),默认析构函数会被自动调用
    // 这里obj对象生命周期结束,自动生成的析构函数会调用myCustomObject的析构函数

    return 0;
}

代码结果:

编译器自动生成的析构函数机制:
        1、编译器自动生成的析构函数对内置类型不做处理。
        2、对于自定义类型,编译器会再去调用它们自己的默认析构函数。 

6. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。

拷贝构造函数

        在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎。

        那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?

  拷贝构造函数的概念

概念:只有单个形参,该形参是对本类类型对象的引用(一般常用从const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

#include <iostream>

using namespace std;

class Date
{
public:
	Date(int year = 0, 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;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2021, 5, 31);
	Date d2(d1); // 用已存在的对象d1创建对象d2

	return 0;
}

  拷贝构造函数的特性

1、拷贝构造函数是构造函数的一个重载形式。

        拷贝构造函数的函数名也与类名相同。

2、拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,
因为会引发无穷递归调用。

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d) // 正确写法
	//Date(const Date d) // 错误写法:编译报错,会引发无穷递归
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};

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

        要调用拷贝构造函数就需要先传参,若传参使用传值传参,那么在传参过程中又需要进行对象的拷贝构造,如此循环往复,最终引发无穷递归调用。 

注意:自定义类型的对象进行函数传参时,一般推荐使用引用传参。使用传值传参也可以,但每次传参时都会调用拷贝构造函数。

3、若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按
字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

#include <iostream>

using namespace std;

class Date
{
public:
	Date(int year = 0, int month = 1, int day = 1)// 构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "年" << _month << "月" << _day << "日" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2021, 5, 30);
	Date d2(d1); // 用已存在的对象d1创建对象d2
	d1.Print();
	d2.Print();
	return 0;
}

代码结果:

#include <iostream>

using namespace std;

class Time
{
public:
	Time()
	{
		_hour = 1;
		_minute = 1;
		_second = 1;
	}
	Time(const Time& t)
	{
		cout << "Time::Time(const Time&)" << endl;
		_hour = t._hour;
		_minute = t._minute;
		_second = t._second;
	}
private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{
private:
	// 基本类型(内置类型)
	int _year = 1;
	int _month = 1;
	int _day = 1;
	// 自定义类型
	Time _t;
};

int main()
{
	Date d1;

	// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数
	// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构造函数
	Date d2(d1);
	return 0;
}

代码结果:

编译器自动生成的拷贝构造函数机制:
 1、编译器自动生成的拷贝构造函数对内置类型会完成浅拷贝(值拷贝)。
 2、对于自定义类型,编译器会再去调用它们自己的默认拷贝构造函数。

4、编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗?
当然像日期类这样的类是没必要的。那么下面的类呢?

#include <malloc.h>
#include <stdlib.h>

typedef int DataType;

class Stack
{
public:
	Stack(size_t capacity = 10)
	{
		_array = (DataType*)malloc(capacity * sizeof(DataType));
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			return;
		}
		_size = 0;
		_capacity = capacity;
	}
	void Push(const DataType& data)
	{
		// CheckCapacity();
		_array[_size] = data;
		_size++;
	}
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	DataType* _array;
	size_t _size;
	size_t _capacity;
};

int main()
{
	Stack s1;
	s1.Push(1);
	s1.Push(2);
	s1.Push(3);
	s1.Push(4);
	Stack s2(s1);
	return 0;
}

代码结果:

        这里会发现上面的程序会崩溃掉?这里就需要我们以后讲的深拷贝去解决。

注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请
时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

5、拷贝构造函数典型调用场景:

  •         使用已存在对象创建新对象。
  •         函数参数类型为类类型对象。
  •         函数返回值类型为类类型对象。

#include <iostream>

using namespace std;

class Date
{
public:
	Date(int year, int minute, int day)
	{
		cout << "Date(int,int,int):" << this << endl;
	}
	Date(const Date& d)
	{
		cout << "Date(const Date& d):" << this << endl;
	}
	~Date()
	{
		cout << "~Date():" << this << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

Date Test(Date d)
{
	Date temp(d);
	return temp;
}

int main()
{
	Date d1(2022, 1, 13);
	Test(d1);
	return 0;
}

代码结果:

注意:为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用尽量使用引用。

赋值运算符重载

  运算符重载

        C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

d1 == d2;// 可读性高(书写简单)
IsSame(d1, d2);// 可读性差(书写麻烦)

// 目的就是让自定义类型可以像内置类型一样可以直接使用运算符进行操作。 

        函数名字为:关键字operator后面接需要重载的运算符符号。

        函数原型:返回值类型 operator操作符(参数列表)。

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@。
  • 重载操作符必须有一个类类型参数。
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义。
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this。
  • .*  ::  sizeof  ?:  .  注意以上5个运算符不能重载。这个经常在笔试选择题中出现。

以重载 == 运算符作为例子: 

        1、可以将该运算符重载函数作为类的一个成员函数,该函数的第一个形参默认为this指针。

class Date
{
public:
	Date(int year = 0, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "年" << _month << "月" << _day << "日" << endl;
	}
	bool operator==(const Date& d) // 运算符重载函数
	{
		return _year == d._year
			&&_month == d._month
			&&_day == d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};

        2、也可以将该运算符重载函数放在类外面,但此时外部无法访问类中的成员变量,这时我们可以将类中的成员变量设置为共有(public),这样外部就可以访问该类的成员变量了(也可以用友元函数解决该问题)。并且在类外没有this指针,所以此时函数的形参我们必须显示的设置两个。

class Date
{
public:
	Date(int year = 0, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "年" << _month << "月" << _day << "日" << endl;
	}
	int _year;
	int _month;
	int _day;
};
bool operator==(const Date& d1, const Date& d2) // 运算符重载函数
{
	return d1._year == d2._year
		&&d1._month == d2._month
		&&d1._day == d2._day;
}

  赋值运算符重载

1、赋值运算符重载格式

  • 参数类型:const 类类型&,传递引用可以提高传参效率。
  • 返回值类型:类类型&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值。
  • 检测是否自己给自己赋值。
  • 返回*this :要符合连续赋值的含义。

以重载 = 运算符作为例子: 

class Date
{
public:
	Date(int year = 0, int month = 1, int day = 1)// 构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date& operator=(const Date& d)// 赋值运算符重载函数
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
	void Print()// 打印函数
	{
		cout << _year << "年" << _month << "月" << _day << "日" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

2、赋值运算符只能重载成类的成员函数不能重载成全局函数。

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	int _year;
	int _month;
	int _day;
};
// 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
Date& operator=(Date& left, const Date& right)
{
	if (&left != &right)
	{
		left._year = right._year;
		left._month = right._month;
		left._day = right._day;
	}
	return left;
}
// 编译失败:
// error C2801: “operator =”必须是非静态成员

原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。

3、用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。

注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符
重载完成赋值。

#include <iostream>

using namespace std;

class Time
{
public:
	Time()
	{
		_hour = 1;
		_minute = 1;
		_second = 1;
	}
	Time& operator=(const Time& t)
	{
		if (this != &t)
		{
			_hour = t._hour;
			_minute = t._minute;
			_second = t._second;
		}
		return *this;
	}
private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{
private:
	// 基本类型(内置类型)
	int _year = 1970;
	int _month = 1;
	int _day = 1;
	// 自定义类型
	Time _t;
};

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

注意:对于日期类,编译器自动生成的赋值运算符重载函数就可以满足我们的需求,我们可以不用自己写。但是这也不意味着所有的类都不用我们自己写赋值运算符重载函数,当遇到一些特殊的类,我们还是得自己动手写赋值运算符函数的。

 注意区别以下代码所调用的函数:

Date d1(2021, 6, 1);// 构造函数
Date d2(d1);// 拷贝构造函数
Date d3 = d1;// 拷贝构造函数

构造函数和赋值运算符重载函数的使用场景: 

        拷贝构造函数:用一个已经存在的对象去构造初始化另一个即将创建的对象。
        赋值运算符重载函数:在两个对象都已经存在的情况下,将一个对象赋值给另一个对象。

const成员

  const修饰类的成员函数

        将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰的是类成员函数隐含的this指针,表明在该成员函数中不能对this指针指向的对象进行修改。

#include <iostream>

using namespace std;

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << "Print()" << endl;
		cout << "year:" << _year << endl;
		cout << "month:" << _month << endl;
		cout << "day:" << _day << endl << endl;
	}
	void Print() const
	{
		cout << "Print()const" << endl;
		cout << "year:" << _year << endl;
		cout << "month:" << _month << endl;
		cout << "day:" << _day << endl << endl;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};

int  main()
{
	Date d1(2022, 1, 13);
	d1.Print();
	const Date d2(2022, 1, 13);
	d2.Print();
	return 0;
}

代码结果:

思考下面几个问题(经典面试题):
1、const对象可以调用非const成员函数吗?
2、非const对象可以调用const成员函数吗?
3、const成员函数内可以调用其他的非const成员函数吗?
4、非cosnt成员函数内可以调用其他的cosnt成员函数吗?

答案是:不可以、可以、不可以、可以

解释如下:
1、非const成员函数,即成员函数的this指针没有被const所修饰,我们传入一个被const修饰的对象,用没有被const修饰的this指针进行接收,属于权限的放大,函数调用失败。
2、const成员函数,即成员函数的this指针被const所修饰,我们传入一个没有被const修饰的对象,用被const修饰的this指针进行接收,属于权限的缩小,函数调用成功。
3、在一个被const所修饰的成员函数中调用其他没有被const所修饰的成员函数,也就是将一个被const修饰的this指针的值赋值给一个没有被const修饰的this指针,属于权限的放大,函数调用失败。
4、在一个没有被const所修饰的成员函数中调用其他被const所修饰的成员函数,也就是将一个没有被const修饰的this指针的值赋值给一个被const修饰的this指针,属于权限的缩小,函数调用成功。

取地址及const取地址操作符重载

        取地址操作符重载和const取地址操作符重载,这两个默认成员函数一般不用自己重新定义,使用编译器自动生成的就行了:

class Date
{
public:
	Date* operator&() // 取地址操作符重载
	{
		return this;
	}
	const Date* operator&()const // const取地址操作符重载
	{
		return this;
	}
private:
	int _year;
	int _month;
	int _day;
};

注意:这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!

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

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

相关文章

扫码枪与Input的火花

文章目录 前言一、需求&#xff1a;交互细节二、具体实现两个核心的函数&#xff1a;自动聚焦 三&#xff0c;扩展知识input 与 change的区别 前言 在浏览器扫描条形码获取条形的值&#xff0c;再操作对应的逻辑。这是比较常见的业务&#xff0c;这里记录实际操作。 其中PC端…

LeetCode2095删除链表的中间节点

题目描述 给你一个链表的头节点 head 。删除 链表的 中间节点 &#xff0c;并返回修改后的链表的头节点 head 。长度为 n 链表的中间节点是从头数起第 ⌊n / 2⌋ 个节点&#xff08;下标从 0 开始&#xff09;&#xff0c;其中 ⌊x⌋ 表示小于或等于 x 的最大整数。对于 n 1、…

Leaflet系列——【一】初识Leaflet与Leaflet视图操作

初识Leaflet&#xff08;vue3 &#xff09; 前言&#xff1a;当你熟悉了openlayer、mapbox、cesium等一些GIS框架之后&#xff0c;对于我们开发来说其实他们的本质就是往瓦片上面叠加图层、【点、线、面、瓦片、geoJson、热力图、图片、svg等等】都是一层层的Layer图层&#xf…

AI与人类生活的融合:安克创新CEO阳萌的深度洞见

安克创新CEO阳萌分享了他对人工智能未来发展的深刻见解。阳萌不仅深入探讨了大模型技术的应用前景&#xff0c;还对AI与人类生活的融合提出了引人入胜的思考。以下是对这次访谈内容的总结和分析。 大模型技术的现实应用 阳萌提到&#xff0c;尽管大模型在处理通用知识方面表…

拥有一个生产女朋友的工厂,是什么体验

正所谓&#xff0c;“旱的旱死&#xff0c;涝的涝死”&#xff0c;在这个充满竞争的编程界&#xff0c;我们似乎总是忙于解决bug和优化算法&#xff0c;以至于个人生活常常被忽略。但别担心&#xff0c;今天&#xff0c;我们要用一种独特的方式&#xff0c;解决这个“问题”。 …

OpenAI Whisper 语音转文本实验

为了实现语音方式与大语言模型的对话&#xff0c;需要使用语音识别&#xff08;Voice2Text&#xff09;和语音输出&#xff08;Text2Voice&#xff09;。感觉这项技术已比较成熟了&#xff0c;国内也有许多的机构开发这项技术&#xff0c;但是像寻找一个方便测试的技术居然还不…

根据后端返回下拉请求地址,前端动态请求拿到下拉数据渲染

完整代码如下&#xff1a; <template> <!-- 资源列表页 --> <div> <div> <i click"$router.go(-1)" style" color: #409eff; cursor: pointer; margin-right: 5px; font-size: 18px; " class"el-icon-back" ><…

C++ 关键字 :using

在 C 庞大语法体系中&#xff0c; using 关键字十分的灵活多用&#xff0c;它可不简单。 除了常规的引入命名空间之外&#xff0c;它还可用于引入枚举类型枚举器、定义常规类型别名、模板类型别名等。在定义常规类型别名方面与C语言中的typedef、#define与之相似&#xff0c;但…

jupyter notebook中调整图片大小

截屏 ctrl V 这个目前只能保证是截屏大小&#xff0c;改变不了&#xff0c;要么之久 把图形缩小后再截图 感觉很模糊 png文件导入 markdown 代码1 <img src"./1.png" width250 height200>markdown 代码2 <img src"./1.png" width938 height…

文献速递:多模态深度学习在医疗中的应用--多模式婴儿脑分割技术:模糊引导深度学习

Title 题目 Multimodal Infant Brain Segmentation by Fuzzy-informed Deep Learning 多模式婴儿脑分割技术&#xff1a;模糊引导深度学习 01 文献速递介绍 日益普及的非侵入式婴儿脑磁共振图像&#xff08;MRI&#xff09;为准确理解脑主要发展轨迹的动态性提供了机会&…

普中STM32F103ZET6开发板让DS0和DS1两个LED同时亮

欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一.前言 二.代码 三.运行效果 一.前言 在这套stm32教程中,只教学了如何亮DS0,而没有教学如何亮DS1。 二.代码 main.c #include "stm32f10x.h"void Syst

一篇文章告诉你聚类算法的作用和怎么用聚类算法!建议收藏!(下篇)

EM聚类 EM聚类 基于概率分布对数据进行建模&#xff0c;通过迭代的期望和最大化步骤来估计模型参数&#xff0c;并将数据分为不同的聚类。EM聚类通常用于处理混合分布的数据&#xff0c;其中每个聚类被建模为一个概率分布。 原理介绍 EM聚类的核心思想是将数据集中的每个样本…

二分答案(区间范围)

D. Jumping Through Segments 输入数据 4 5 1 5 3 4 5 6 8 10 0 1 3 0 2 0 1 0 3 3 3 8 10 18 6 11 4 10 20 0 5 15 17 2 2 输出范围 7 0 5 13#include<bits/stdc.h> #define int long long using namespace std; typedef pair<char,int>PII; const int N2e510;…

应急响应-Windows-挖矿病毒

随着虚拟货币市场的繁荣&#xff0c;挖矿病毒已成为网络安全领域一大挑战。该类病毒利用计算机资源进行加密货币的挖掘&#xff0c;给个人用户和企业网络带来了严重的安全风险。本文将针对挖矿病毒的应急响应和防范措施进行分析和总结。 一.判断挖矿病毒 服务器突然发现CPU资…

树莓派发送指令控制FPGA板子上的流水灯程序

文章目录 前言一、树莓派简介二、整体实现步骤三、树莓派设置四、树莓派串口代码五、Verilog代码5.1 串口接收模块5.2 流水灯模块 六、quartus引脚绑定七、 运行效果总结参考 前言 ​ 本次实验的目的是通过树莓派和FPGA之间的串口通信&#xff0c;控制FPGA开发板上的小灯。实验…

OpenAI 发布新款大型语言模型 GPT-4o,带大家了解最新ChatGPT动态。

OpenAI 发布新款大型语言模型 GPT-4o 昨日OpenAI 举办了一场线上活动&#xff0c;正式发布了其最新研发的 AI 模型 GPT-4o&#xff0c;并详细介绍了该模型的强大功能和未来发展规划。此次发布标志着 AI 技术的重大突破&#xff0c;为用户提供了更加便捷、高效的 AI 工具&#…

css多种布局方式

css多种布局方式 简介标准流布局&#xff08;主要依赖margin\padding&#xff09;浮动布局&#xff08;float&#xff09;定位布局&#xff08;position&#xff09;弹性布局&#xff08;flex&#xff09;网格布局&#xff08;grid&#xff09;多列布局&#xff08;column&…

【论文阅读】<YOLOP: You Only Look Once for PanopticDriving Perception>

Abstract 全视驾驶感知系统是自动驾驶的重要组成部分。一个高精度的实时感知系统可以帮助车辆在驾驶时做出合理的决策。我们提出了一个全视驾驶感知网络&#xff08;您只需寻找一次全视驾驶感知网络&#xff08;YOLOP&#xff09;&#xff09;&#xff0c;以同时执行交通目标检…

7.STL中string的一些超常用函数 (附习题)

目录 1.find 2.atoi 3.to_string 4.getline 【leetcode 习题】 387.字符串中的第一个唯一字符 125. 验证回文串 1.find 1.查找第一次出现的目标字符串&#xff1a;说明&#xff1a;如果查找成功则输出查找到的第一个位置&#xff0c;否则返回-1&#xff1b; s1.find(s2…

嗨动PDF编辑器怎么删除pdf空白页?教程来啦!

嗨动PDF编辑器怎么删除pdf空白页&#xff1f;在日常的工作和学习中&#xff0c;PDF文件因其跨平台兼容性和稳定性而备受青睐。然而&#xff0c;在编辑PDF文件时&#xff0c;我们往往会遇到一些令人头疼的问题&#xff0c;其中最常见的就是空白页。空白页不仅浪费了宝贵的存储空…