当前位置: 首页 > news >正文

【C++ 类和对象 进阶篇】—— 逻辑森林的灵动精灵,舞动类与对象的奇幻圆舞曲

欢迎来到ZyyOvO的博客✨,一个关于探索技术的角落,记录学习的点滴📖,分享实用的技巧🛠️,偶尔还有一些奇思妙想💡
本文由ZyyOvO原创✍️,感谢支持❤️!请尊重原创📩!欢迎评论区留言交流🌟
个人主页 👉 ZyyOvO
本文专栏➡️C++ 进阶之路

创作者

各位于晏,亦菲们请看

文章目录

  • ==各位于晏,亦菲们请看==
  • 1、类的默认成员函数
  • 2、构造函数
  • 3、析构函数
  • 4、拷贝构造函数
  • 5、运算符重载
    • 5.1、赋值运算符重载
    • 5.2、const成员函数
    • 5.3、 mutable关键字
    • 5.4、取地址运算符重载
  • 6、完整的Date类实现
  • ==写在最后==

1、类的默认成员函数

类的默认成员函数是编译器在没有显式定义相应函数时自动生成的函数。这些函数通常是为了处理类对象的生命周期管理,包括对象的创建、复制、赋值和销毁等操作。确保即使开发者没有显式提供某些操作,编译器也能提供默认实现,以保证程序的基本功能。
通常包括以下几个函数:
类的六个默认成员函数

  • 默认构造函数
  • 拷贝构造函数
  • 拷贝赋值重载
  • 析构函数
  • 取地址操作符重载
    这些默认成员函数由编译器在没有显式定义时自动生成,它们通常执行逐成员的浅拷贝或简单的资源释放。对于包含动态内存或复杂资源管理的类,通常需要显式实现这些函数,确保资源的正确管理。
    C++11之后还引入了两个成员函数:
  • 移动构造函数(C++11引入)
  • 移动赋值重载(C++11引入)
    本文我们重点讲解前五个默认成员函数

2、构造函数

构造函数的特点:

  • 函数名称与类名相同。
  • 没有返回类型(甚至没有void)。
  • 自动调用:每当创建对象时,构造函数会被自动调用。
  • 可以有多个构造函数(构造函数重载)。
  • 不能被显式调用:构造函数只能在对象创建时由编译器调用。

构造函数的类型:

  • 默认构造函数(Default Constructor)
  • 定义:没有参数或者所有参数都有默认值的构造函数。 作用:初始化对象时如果没有传递参数,默认构造函数会被调用。
  • 编译器自动生成:如果没有定义任何构造函数,编译器会生成一个默认构造函数;如果定义了其他构造函数(如带参数的构造函数),则编译器不会自动生成默认构造函数。
  • 无参构造函数、全缺省构造函数、我们不显示定义时编译器默认生成的构造函数,都叫做默认构造函数
  • 但是这三个函数有且只有⼀个存在,不能同时存在。无参构造函数和全缺省构造函数虽然构成函数重载,但是调用时会存在歧义。要注意很多同学会认为默认构造函数是编译器默认生成那个叫默认构造,实际上无参构造函数、全缺省构造函数也是默认构造,总结一下就是不传实参就可以调用的构造就叫默认构造函数

编译器默认成的构造函数,对内置类型成员变量的初始化没有要求,也就是说是是否初始化是不确定的,取决于编译器。对于自定义类型成员变量,要求调用这个成员变量的默认构造函数初始化。如果这个成员变量没有默认构造函数,那么就会编译出错,我们要初始化这个成员变量,需要用初始化列表!(初始化列表后面再讲)

以Date类为例:如果我们不显示定义构造函数,编译器会自动生成默认默认构造函数

class Date
{
public:
private:int _year;int _month;int _day;
};

无参构造函数:

Date()
{_year = 2025;_month = 1;_day = 15;
}

全缺省构造函数:

Date(int year=2025, int month=1, int day=15)
{_year = year;_month = month;_day = day;
}

以上两种构造函数以及编译器自动生成的构造函数都属于默认构造函数

  • 带参数构造函数(Parameterized Constructor)
  • 定义:包含一个或多个参数的构造函数,允许在创建对象时为对象成员传递初始值。
  • 作用:通过传递不同的参数,创建对象时可以初始化不同的值。
 Date(int year, int month, int day)
{_year = year;_month = month;_day = day;
}

3、析构函数

  • 定义:析构函数在对象生命周期结束时调用,用于释放对象占用的资源。
  • 自动生成:如果你没有定义析构函数,编译器会自动生成一个默认析构函数。它会销毁对象并释放资源。但如果类中有动态内存分配,或者存在资源申请,则需要显式定义析构函数。

析构函数的特点:

  • 析构函数的名称必须与类名相同,但在前面加上波浪号 ~。例如,类 Date 的析构函数名称应该是 ~Date()。
  • 析构函数没有返回类型,(包括 void)。
  • 析构函数不能带有参数,因此无法重载
  • 自动调用:析构函数由编译器在对象生命周期结束时自动调用。当一个对象超出其作用域时,或显式调用 delete删除一个动态分配的对象时,析构函数会被调用。
  • 调用顺序: 对于 局部对象,析构函数在对象超出作用域时被自动调用。 对于 动态分配的对象,析构函数在 delete 语句执行时被调用。
    跟构造函数类似,我们不写编译器自动生成的析构函数对内置类型成员不做处理,对于自定义类型成员会调用它的析构函数。

析构函数的基本语法:

class Date 
{
public:~Date(){//完成对资源的清理和释放}
};

析构函数的作用:
析构函数的作用是清理对象在其生命周期内所占用的资源。常见的资源包括:

  • 动态内存: 通过 new 动态分配的内存需要在析构函数中通过 delete 或 delete[] 释放。
  • 文件句柄、数据库连接、网络资源:如果对象打开了文件或建立了网络连接,析构函数应负责关闭它们。
  • 其他资源:任何外部资源(例如锁、线程、内存映射等)都应在析构函数中清理。

析构函数的自动调用
析构函数的调用通常是在以下情况下自动发生:

  • 对象生命周期结束时:当局部对象超出作用域时,析构函数会自动调用。例如,当 main() 函数结束时,局部对象的析构函数会被调用。

  • 动态分配的对象:如果对象是通过 new 分配的,那么在调用 delete 时,析构函数会被自动调用。

  • ⼀个局部域的多个对象,C++规定后定义的先析构。

简单的析构函数示例:

#include<iostream>
using namespace std;
class MyClass {
public:MyClass() {ptr = new int[10];  // 动态分配内存cout << "Constructor: Memory allocated" << endl;}~MyClass() {delete[] ptr;  // 释放内存cout << "Destructor: Memory deallocated" << endl;}
private:int* ptr;
};
int main() {MyClass obj;  // 创建对象时调用构造函数,释放内存时调用析构函数return 0;
}

4、拷贝构造函数

拷贝构造函数是一个特殊成员函数,用于通过另一个同类型的对象来初始化一个对象。如果⼀个构造函数的第⼀个参数是自身类类型的引用,且任何额外的参数都有默认值,则此构造函数也叫做拷贝构造函数,也就是说拷贝构造是⼀个特殊的构造函数。它通常在以下几种情况下被调用:

  • 对象作为函数参数传递时(按值传递)
  • 从函数返回一个对象(返回值时)
  • 初始化一个对象为另一个同类型对象的副本(拷贝初始化)

拷贝构造函数的特点:

  • 拷贝构造函数是构造函数的⼀个重载
  • 拷贝构造函数的第⼀个参数必须是类类型对象的引用,使用传值方式编译器直接报错,因为语法逻辑上会引发无穷递归调用。拷贝构造函数也可以多个参数,但是第⼀个参数必须是类类型对象的引用,后面的参数必须有缺省值
  • C++规定自定义类型对象进行拷贝必须调用拷贝构造,所以这里自定义类型传值传参和传值返回都会调用拷贝构造完成。
  • 若未显式定义拷贝构造,编译器会生成自动生成拷贝构造函数。自动生成的拷贝构造对内置类型成员变量会完成值拷贝/浅拷贝(⼀个字节⼀个字节的逐字节拷贝),对自定义类型成员变量会调用他的拷贝构造。
    拷贝构造
    拷贝构造的基本语法:
 ClassName(const ClassName& other){//完成对象的拷贝}

ClassName 是类名。
const ClassName& other 是另一个同类型对象的引用,表示将要复制的数据。
关键点:

  • const:拷贝构造函数的参数必须是 const,这样可以保证传递的对象不被修改。
  • &:参数是引用类型,避免了对象的拷贝开销。
  • 传递方式:拷贝构造函数通常使用按引用传递对象,而不是按值传递,防止出现不必要的递归调用。

拷贝构造函数的使用场景:

  • 按值传递参数时: 当对象作为函数参数传递,并且该对象以值的方式传递时,会调用拷贝构造函数。
void function(MyClass obj) {// 对象 obj 会调用拷贝构造函数
}
MyClass obj1;
function(obj1);  // 这里会调用拷贝构造函数
  • 返回值时: 当一个函数返回一个对象时,编译器会使用拷贝构造函数来复制返回值。
MyClass createObject() {MyClass obj;return obj;  // 这里会调用拷贝构造函数
}
  • 拷贝初始化: 当一个对象被另一个相同类型的对象初始化时,也会调用拷贝构造函数。
MyClass obj1;
MyClass obj2(obj1);// MyClass obj2 = obj1; 或者写成这样// 这里会调用拷贝构造函数

默认的拷贝构造函数:
如果没有显式定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数,通常执行浅拷贝。这意味着它会简单地复制成员变量的值,对于指针成员,它只会复制指针的值(即地址),不会分配新的内存。这样会导致多个对象共享相同的内存资源,可能会出现内存泄漏或意外的资源共享。

class MyClass {
public:int* data;MyClass(int val) {data = new int(val);}~MyClass() {delete data;}
};MyClass obj1(10);
MyClass obj2 (obj1);  // 默认拷贝构造函数,浅拷贝

深拷贝的需求
如果类的成员变量涉及动态内存分配,默认的浅拷贝可能导致问题。拷贝构造函数需要进行深拷贝,即为每个对象分配新的内存空间,以避免不同对象共享同一内存。

class MyClass {
public:int* data;MyClass(int val) {data = new int(val);}// 手动定义深拷贝构造函数MyClass(const MyClass& other) {data = new int(*other.data);  // 为每个对象分配新的内存}~MyClass() {delete data;}
};
MyClass obj1(10);
MyClass obj2 = obj1;  // 调用深拷贝构造函数

注意:

  • 如果没有指针成员,且不涉及动态内存分配,可以使用默认的浅拷贝
  • 如果类包含指针成员或动态分配的内存,必须自定义拷贝构造函数,并使用深拷贝。
  • 注意自身赋值:在拷贝构造函数中,通常不需要处理自赋值问题(因为自身赋值问题通常出现在赋值运算符重载中),但实现赋值运算符重载时,需要特别注意自身赋值情况。

5、运算符重载

在 C++ 中,运算符重载(Operator Overloading)允许你为自定义类型定义或修改运算符的行为,使得可以使用运算符来操作类的对象。通过运算符重载,类的对象可以像内建类型一样使用运算符进行各种操作(如加法、减法等)。

  • 运算符重载是具有特殊名字的函数,他的名字是由operator和后面要定义的运算符共同构成。和其他函数⼀样,它也具有其返回类型和参数列表以及函数体。
ReturnType operator符号(参数列表)
{//函数体
}

ReturnType:返回类型,通常是操作后的结果类型。
operator符号:运算符的标识符,例如 +、-、*、[]、= 等。
参数列表:指定操作数的类型和数量。

  • 重载运算符函数的参数个数和该运算符作用的运算对象数量⼀样多。⼀元运算符有⼀个参数,⼆元
    运算符有两个参数,⼆元运算符的左侧运算对象传给第⼀个参数,右侧运算对象传给第⼆个参数。

  • 如果⼀个重载运算符函数是成员函数,则它的第⼀个运算对象默认传给隐式的this指针,因此运算符重载作为成员函数时,参数比运算对象少⼀个。

  • 运算符重载以后,其优先级和结合性与对应的内置类型运算符保持⼀致。

  • 不能通过连接语法中没有的符号来创建新的操作符:比如operator@。

  • .* :: (域作用解析符)sizeof ?: . 等运算符不能重载

  • 重载++运算符时,有前置++和后置++,运算符重载函数名都是operator++,无法很好的区分。
    C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,方便区分。

  • 重载<<和>>时,需要重载为全局函数,因为重载为成员函数,this指针默认抢占了第⼀个形参位置,第⼀个形参位置是左侧运算对象,调用时就变成了对象<<cout,不符合使用习惯和可读性。重载为全局函数把 ostream/istream 放到第⼀个形参位置就可以了,第⼆个形参位置当类类型对象。

举个例子:

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;}bool operator==(const Date& d){return _year == d._year&& _month == d._month&& _day == d._day;}Date& operator++(){cout << "前置++" << endl;//...return *this;}Date operator++(int){Date tmp; cout << "后置++" << endl;//...return tmp;}
private:int _year;int _month;int _day;
};

5.1、赋值运算符重载

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

为什么需要重载赋值运算符?
默认的赋值运算符执行浅拷贝,即直接复制对象的成员变量。如果类中有指针成员或者动态分配的内存,浅拷贝可能导致内存泄漏或多重释放等问题。因此,当类中涉及动态内存时,你必须手动实现赋值运算符,以确保深拷贝

赋值运算符重载的特点:

  • 赋值运算符重载是⼀个运算符重载,规定必须重载为成员函数。赋值运算重载的参数建议写成 const 当前类类型引用,否则会传值传参会有拷贝
  • 有返回值,且建议写成当前类类型引用。引用返回可以提高效率,有返回值目的是为了支持连续赋
    值场景。
  • 没有显式实现时,编译器会自动生成⼀个默认赋值运算符重载,默认赋值运算符重载行为跟默认拷
    贝构造函数类似,对内置类型成员变量会完成值拷贝/浅拷贝(⼀个字节⼀个字节的拷贝),对自定义
    类型成员变量会调用它的赋值重载函数。

如果需要显式实现赋值运算符重载要注意以下几点:

  • 检查自赋值:如果左边对象和右边对象是同一个对象(即自赋值),则无需执行任何操作。
  • 释放当前资源:在执行赋值之前,应该释放当前对象占用的资源,以避免内存泄漏。
  • 执行深拷贝:将右边对象的数据复制到左边对象的成员变量中。
  • 返回*this:以支持链式赋值操作。

实现简单的赋值运算符:

class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){cout << " Date(const Date& d)" << endl;_year = d._year;_month = d._month;_day = d._day;}// 传引用返回减少拷贝// d1 = d2;Date& operator=(const Date& d){// 注意自身赋值情况if (this != &d){_year = d._year;_month = d._month;_day = d._day;}// d1 = d2表达式的返回对象应该为d1,也就是*thisreturn *this;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};

5.2、const成员函数

定义:

  • const 成员函数是指那些不会修改对象状态的成员函数。它是通过在成员函数的声明和定义后加上 const 关键字来标识的。const 成员函数保证不会修改对象的成员变量,确保对象的状态在调用该函数时保持不变。
  • const实际修饰该成员函数隐含的this指针。表明在该成员函数中不能对类的任何成员进行修改。

const成员函数的作用:

  • 保证不修改对象状态:const 成员函数承诺不会修改对象的数据,这对于许多场合(如传递常量对象或在多线程中共享对象)非常重要。
  • 编译时检查:通过将成员函数声明为 const,编译器可以帮助检查是否存在意外修改对象的情况。如果在 const成员函数中尝试修改对象的成员变量,编译器会报错。
  • 提高可读性和安全性:它明确表示该函数是只读操作,不会改变对象的状态,有助于代码的可读性和维护性。

例如Date类中的Print函数:修饰为const成员函数,它只读取对象的状态,不修改任何成员变量。

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

const成员函数的限制:

  • 不能修改成员变量:const 成员函数中不能修改对象的成员变量,除非这些成员变量被声明为 mutable
  • 不能调用非 const成员函数:const 成员函数不能调用任何非 const 成员函数,因为后者可能会修改对象的状态。

5.3、 mutable关键字

在 C++ 中,mutable 关键字用于修饰类的成员变量,允许在 const 成员函数 中修改该成员变量。通常,const 成员函数表示该函数不会修改对象的状态,但有时我们希望某些成员变量在这些函数中仍然可以修改。使用 mutable 可以实现这一点。

mutable关键字的使用:

class MyClass {
public:MyClass(int counter=0){_counter = counter;}// const 成员函数可以修改 mutable 成员变量void incrementCounter() const {_counter++;}void displayCounter() const {cout << "Counter: " << _counter << endl;}
private:mutable int _counter;  // mutable 成员变量
};
int main() {MyClass obj;obj.incrementCounter();  // 修改 mutable 成员变量obj.displayCounter();  // 输出:Counter: 1return 0;
}

mutable 的使用场景:

  • 缓存:有时我们希望在 const 成员函数中修改某些缓存数据,这时可以使用 mutable。
  • 计数器:在一些只读操作中(如访问次数计数器),需要更新计数器而不影响对象的逻辑状态。
  • 延迟计算:可以用于延迟计算或懒加载(lazy loading)等操作。

mutable的注意事项:

  • 只修改 mutable 成员:mutable 关键字只影响被修饰的成员变量,其他成员变量依然受到 const 限制
  • const成员函数的约束:mutable 使得 const成员函数能够修改成员变量,但不会改变对象的外部状态。它仍然保持对象的“逻辑不可变性”,但允许修改内部的、仅对函数内部有意义的数据。

5.4、取地址运算符重载

取地址运算符(&)用于获取对象的内存地址。虽然我们可以直接使用 & 来获取对象的地址,但如果你需要在自定义类中对取地址运算符进行重载,则可以通过重载 operator& 来实现,通常情况下是返回当前对象的this指针

  • 取地址运算符重载分为普通取地址运算符重载和const取地址运算符重载

取地址运算符通常不常见于需要重载的运算符,因为它通常只是返回对象的地址。编译器默认生成的重载函数就可以满足我们的需求,不需要显式实现。

在一些特殊场景下:如(模拟智能指针、内存管理等)场景下发挥作用
或者当我们不想将当前类对象的地址被获取,可以通过重载取地址运算符的重载返回特定的地址

class Date
{
public:Date * operator&(){return this;// return nullptr;}const Date * operator&()const{return this;// return nullptr;}private:int _year; // 年int _month; // 月int _day; // 日
};

6、完整的Date类实现

  • Date.h 头文件
class Date{friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);
public:Date(int year = 2005, int month = 5, int day = 18);bool DateCheck();void print();int GetMonthDay(int year,int month){static int ArrMonth[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){return 29;}return ArrMonth[month];}bool operator<(const Date& d) const;bool operator<=(const Date& d) const;bool operator>(const Date& d) const;bool operator>=(const Date& d) const;bool operator==(const Date& d) const;bool operator!=(const Date& d) const;Date& operator+=(int day);Date operator+(int day);Date& operator-=(int day);Date operator-(int day);int operator-(const Date& d)const;Date& operator++();Date  operator++(int);Date& operator--();Date  operator--(int);private:int _year;int _month;int _day;
};
  • Date.cpp 源文件
#include"Date.h"bool Date::DateCheck()
{if (_month < 1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month)){return false;}return true;
}Date ::Date (int year , int month, int day)
{_year = year;_month = month;_day = day;if (!DateCheck()){cout << "日期非法" << endl;print();}
}void Date::print()
{cout << _year << "/" << _month << "/" << _day << endl;}
Date& Date::operator+=(int day)
{if (day < 0){return *this -= (-day);}_day += day;while (_day > GetMonthDay(_year,_month)){_day -= GetMonthDay(_year,_month);++_month;if (_month == 13){++_year;_month = 1;}}return *this;
}Date Date:: operator+(int day)
{Date tmp=*this;tmp._day += day;while (tmp._day > GetMonthDay(tmp._year,tmp. _month)){tmp._day -= GetMonthDay(tmp._year, tmp._month);++tmp._month;if (tmp._month == 13){++tmp._year;tmp._month = 1;}}return tmp;
}bool Date::operator<(const Date& d) const{if (_year < d._year){return true;}else if (_year == d._year){if (_month < d._month){return true;}else if (_month == d._month){return _day < d._day;}}return false;
}
bool Date::operator<=(const Date& d) const
{return *this < d || *this == d;
}
bool Date::operator>(const Date& d) const
{return !(*this <= d);
}
bool Date::operator>=(const Date& d) const
{return !(*this < d);
}
bool Date::operator==(const Date& d) const
{return _year == d._year &&_month == d._month &&_day == d._day;
}
bool Date::operator!=(const Date& d) const{return !(*this == d);
}int Date::operator-(const Date& d) const
{int flag = 1;Date max = *this;Date min = d;if (*this < d){max = d;min = *this;flag = -1;}int count = 0;while (min != max){++min;++count;}if (1 == flag){return count;}elsereturn -count;
}Date& Date::operator++()
{*this+=1;return *this;
}
Date Date::operator++(int)
{Date tmp = *this;*this += 1;return tmp;
}Date& Date:: operator--()
{*this -= 1;return *this;
}
Date Date:: operator--(int)
{Date tmp = *this;*this -= 1;return tmp;
}Date& Date::operator-=(int day)
{if (day < 0){return *this += (-day);}_day-= day;while (_day <= 0){--_month;if (_month == 0){_month = 12;--_year;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date::operator-(int day)
{Date tmp = *this;tmp -= day;return tmp;
}ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}istream& operator>>(istream& in, Date& d)
{while (1){cout << "请依次输入年月日:>";in >> d._year >> d._month >> d._day;if (!d.DateCheck()){cout << "输入日期非法:";d.print();cout << "请重新输入!!!" << endl;}else{break;}}return in;
}

写在最后

如果你觉得这篇文章对你有所帮助,请为我的博客 点赞👍收藏⭐️ 评论💬或 分享🔗 支持一下!你的每一个支持都是我继续创作的动力✨!🙏
如果你有任何问题或想法,也欢迎 留言💬 交流,一起进步📚!❤️ 感谢你的阅读和支持🌟!🎉
祝各位大佬吃得饱🍖,睡得好🛌,日有所得📈,逐梦扬帆⛵!

祝福

相关文章:

【C++ 类和对象 进阶篇】—— 逻辑森林的灵动精灵,舞动类与对象的奇幻圆舞曲

欢迎来到ZyyOvO的博客✨&#xff0c;一个关于探索技术的角落&#xff0c;记录学习的点滴&#x1f4d6;&#xff0c;分享实用的技巧&#x1f6e0;️&#xff0c;偶尔还有一些奇思妙想&#x1f4a1; 本文由ZyyOvO原创✍️&#xff0c;感谢支持❤️&#xff01;请尊重原创&#x1…...

【Hive】海量数据存储利器之Hive库原理初探

文章目录 一、背景二、数据仓库2.1 数据仓库概念2.2 数据仓库分层架构2.2.1 数仓分层思想和标准2.2.2 阿里巴巴数仓3层架构2.2.3 ETL和ELT2.2.4 为什么要分层 2.3 数据仓库特征2.3.1 面向主题性2.3.2 集成性2.3.3 非易失性2.3.4 时变性 三、hive库3.1 hive概述3.2 hive架构3.2.…...

前端web

学习笔记&#xff1a; 基本属性 color: 设置文本的颜色。代码&#xff1a;color: red;background-color: 设置元素的背景颜色。background-color: blue;font-size: 设置文本的大小font-size: 16px;font-family: 设置文本的字体font-family: Arial, sans-serif;text-align: 设…...

如何通过 Nginx 实现 CouchDB 集群的负载均衡并监控请求分发

在现代分布式系统中&#xff0c;负载均衡是确保高可用性和性能的关键组件。CouchDB 是一个强大的分布式数据库&#xff0c;而 Nginx 是一个高性能的反向代理和负载均衡器。本文将详细介绍如何通过 Nginx 实现 CouchDB 集群的负载均衡&#xff0c;并监控请求被分发到哪一台 Couc…...

基于代理的RAG实现-Agentic RAG

基于代理的RAG实现-Agentic RAG Agentic RAG 体系结构中&#xff0c;不再被动地响应查询请求&#xff0c;而是主动地分析初步检索到的信息&#xff0c;并基于对任务复杂性的评估&#xff0c;战略性地选择最为合适的工具和方法进行进一步的数据检索和处理。这种多步骤推理和决策…...

ZIP怎么加密?

想要禁止他人随意解压zip压缩包&#xff0c;我们可以加密zip文件&#xff0c;那么zip设置密码的方法有哪些&#xff1f;今天分享三个加密方法 工具&#xff1a;WinRAR&#xff0c;这里需要注意&#xff0c;WinRAR默认压缩格式是.rar&#xff0c;所以我们想要加密zip文件&#…...

森林网络部署,工业4G路由器实现林区组网远程监控

在广袤无垠的林区&#xff0c;每一片树叶的摇曳、每一丝空气的流动&#xff0c;都关乎着生态的平衡与安宁。林区监控正以强大的力量&#xff0c;为这片绿色家园筑起一道坚固的防线。 工业 4G 路由器作为林区监控组网的守护者&#xff0c;凭借着卓越的通讯性能&#xff0c;突破…...

汽车网络信息安全-ISO/SAE 21434解析(上)

目录 概述 第四章-概述 1. 研究对象和范围 2. 风险管理 第五章-组织级网络安全管理 1. 网络安全治理&#xff08;cybersecurity governance&#xff09; 2. 网络安全文化&#xff08;cybersecurity culture) 3. 信息共享&#xff08;Information Sharing) 4. 管理体系…...

一个方法被多个线程同时调用,确保同样参数的调用只能有一个线程执行,不同参数的调用则可以多个线程同时执行

我们知道通过lock一个固定静态object给代码段加同步锁&#xff0c;可以让多个线程的同时调用以同步执行&#xff0c;因此可以利用字典来给不同参数分配不同的静态对象&#xff0c;方法中不同的参数调用锁住各自不同的静态对象即可实现不同参数不加锁&#xff0c;相同参数才加锁…...

军用通信设备通用规范GJB367A-2001试验

军用通信设备通用规范GJB367A-2001通常适用于地面、舰载和机载设备的型式试验验收标准&#xff0c;地面设备分为便携式设备、固定式设备和车载式设备。 GJB367A-2001军用通信设备通用规范规定了军用通信设备或系统的通用要求和检验验收规则以及试验方法。 GJB367A-2001军用通…...

AWS云计算概览(自用留存)

目录 一、云概念概览 &#xff08;1&#xff09;云服务模型 &#xff08;2&#xff09;云计算6大优势 &#xff08;3&#xff09;web服务 &#xff08;4&#xff09;AWS云采用框架&#xff08;AWS CAF&#xff09; 二、云经济学 & 账单 &#xff08;1&#xff09;定…...

AWS云平台上生成式AI通过项目文档内容分析获知项目风险

要在AWS云平台上设计和实施高性能系统&#xff0c;同时使用生成式人工智能识别项目风险来分析项目文档内容。 利用生成式AI分析项目文档并协助风险管理可以显著提高识别和解决AWS上托管的复杂项目中的风险的速度、准确性和效率。通过将AI的功能与传统的项目管理最佳实践相结合&…...

搜广推日常实习面经一

写在前面&#xff1a;除了校招的面经&#xff0c;实习的面经我也会更新&#xff0c;毕竟俺后续可能还要找一段实习。从八股来看&#xff0c;实习的八股更加的八股一点。和校招的面经有点不一样&#xff0c;所以还是可以学习了解一下。总之一句话&#xff1a;面向工作学习&#…...

分布式CAP理论介绍

分布式CAP理论是分布式系统设计中的一个核心概念,由加州大学伯克利分校的Eric Brewer教授在2000年的ACM研讨会上首次提出,随后在2002年由Seth Gilbert和Nancy Lynch从理论上证明。以下是对分布式CAP理论的详细剖析: 文章目录 一、CAP理论的基本概念二、CAP理论的取舍策略三、…...

网格参数化,Mesh parameterization processing

目录 前言1.Barycentric mappingMapping 步骤实例 2.Laplace mapping3.Laplace improvement4.Coding 前言 多边形网格的类型多种多样。本文所实现的网格多边形参数化是指三角多边形。 不同的表示被用来编码三维物体的几何形状。选择一种表示方式取决于在上游的获取过程和下游的…...

路由环路的产生原因与解决方法(1)

路由环路 路由环路就是数据包不断在这个网络传输&#xff0c;始终到达不了目的地&#xff0c;导致掉线或者网络瘫痪。 TTL &#xff08;生存时间&#xff09;&#xff1a;数据包每经过一个路由器的转发&#xff0c;其数值减1&#xff0c;当一个数据包的TTL值为0是&#xff0c;路…...

编程工具箱(免费,离线可用)

https://www.yuque.com/huanmin-4bkaa/ii1hx1?# 《工具箱》 常用的大部分工具都有, 比如mysql可视化 redis可视化, json编辑器, 加解密等(免费,离线可用) 后续也会慢慢的集成...

从Arrays源码学习定义工具类

背景 在日常编码中&#xff0c;一个比较好的实践是&#xff1a;我们把一些业务无关的、可复用的一些通用逻辑&#xff0c;封装成工具类、甚至jar包。这样一方面方便通用代码抽取、代码复用&#xff0c;同时也隔离经常变动的业务代码和不变的通用代码。那如何定义好一个工具类呢…...

Unity中实现倒计时结束后干一些事情

问题描述&#xff1a;如果我们想实现在一个倒计时结束后可以执行某个方法&#xff0c;比如挑战成功或者挑战失败&#xff0c;或者其他什么的比如生成boss之类的功能&#xff0c;而且你又不想每次都把代码复制一遍&#xff0c;那么就可以用下面这种方法。 结构 实现步骤 创建一…...

FPGA随记——时钟时序一些基本知识

原文链接&#xff1a;跨时钟域设计-CSDN博客 前言 CDC&#xff08;clock domain crossing&#xff09;检查&#xff08;跨时钟域的检查&#xff09;是对电路设计中同步电路设计的检查。非同步时钟没有固定的相位关系&#xff0c;这样Setup/Hold不满足而产生了亚稳态是无法避免…...

【微服务】SpringBoot 通用异常处理方案使用详解

目录 一、前言 二、SpringBoot 异常介绍 2.1 SpringBoot 中异常定义 2.1.1 SpringBoot 异常处理机制的重要性 2.2 常用的异常分类 2.3 常用的异常处理解决方案 三、springboot 异常处理操作实践 3.1 springboot自适应错误处理机制 3.1.1 使用默认错误页面 3.1.2 自定义…...

初识MyBatis(详细)

目录 回顾 前提回忆下web应用程序的三层架构&#xff1a; ​编辑 一.什么是MyBatis&#xff1f; 二.Mybatis操作数据库的步骤&#xff1a; 2.1准备工作 2.2配置Mybatis(数据库连接信息&#xff09; 2.3写持久层代码 2.4测试 三.Mybatis配置文件 3.1打印日志 3.2参数传递…...

elementui表单验证,数据层级过深验证失效

先看示例代码&#xff0c;代码为模拟动态获取表单数据&#xff0c;然后动态添加rules验证规则&#xff0c;示例表单内输入框绑定form内第四层&#xff1a; <template><el-form :model"form" :rules"rules" ref"ruleForm" label-width&…...

HTTPS与HTTP:区别及安全性对比

目录 一、基础概念 二、安全性对比 1. 加密传输 2. 身份验证 3. 数据完整性 4. 端口 5. 浏览器展示方式 三、使用场景与性能 1. 使用场景 2. 性能开销 四、成本与维护 五、搜索引擎优化&#xff08;SEO&#xff09; 六、案例分析 七、隐私保护与中间人攻击 八、…...

中国石油大学(华东)自动评教工具(涵盖爬虫的基础知识,适合练手)

我开发了一个用于自动评教的工具&#xff0c;大家可以试着用用&#xff0c;下面是链接。 https://github.com/restrain11/auto_teachingEvaluate 可以点个星吗&#xff0c;感谢&#xff01;&#x1fae1; 以下是我在开发过程中学到的知识 以及 碰到的部分问题 目录 动态爬虫和静…...

蓝桥杯备考:二叉树详解

二叉树的概念和相关术语 二叉树的定义&#xff1a;每个结点度至多为2的树&#xff0c;叫二叉树 二叉树的子树有左右之分不可以随意颠倒顺序&#xff0c;也就是说二叉树是有序树 二叉树根结点左子树右子树 满二叉树&#xff1a;就是把每一层的结点都铺满 满二叉树的性质&#xf…...

大模型微调介绍-Prompt-Tuning

提示微调入门 NLP四范式 第一范式 基于「传统机器学习模型」的范式&#xff0c;如TF-IDF特征朴素贝叶斯等机器算法. 第二范式 基于「深度学习模型」的范式&#xff0c;如word2vec特征LSTM等深度学习算法&#xff0c;相比于第一范式&#xff0c;模型准确有所提高&#xff0c…...

《机器学习》——PCA降维

文章目录 PCA降维简介什么是主成分分析&#xff1f; 主成分的选择与维度确定降维的数学过程PCA降维求解步骤降维后的效果和应用场景中的优势PCA模型API参数Attributes属性PCA对象的方法 PCA降维实例导入所需库导入数据集对数据进行处理创建PCA模型并训练查看训练结果对降维数据…...

【Rust练习】28.use and pub

练习题来自&#xff1a;https://practice-zh.course.rs/crate-module/use-pub.html 1 使用 use 可以将两个同名类型引入到当前作用域中&#xff0c;但是别忘了 as 关键字. use std::fmt::Result; use std::io::Result;fn main() {}利用as可以将重名的内容取别名&#xff1a;…...

VUE学习笔记1__创建VUE实例

核心步骤 <div id"app"><!-- 这里存放渲染逻辑代码 --><h1>{{ msg }}</h1><a href"#">{{count}}</a> </div><!-- 引入在线的开发版本核心包 --> <!-- 引入核心包后全局可使用VUE构造函数 --> <…...

不用PLC和板卡,一台电脑就可以控制伺服

1、前言 大家好&#xff01;我是付工。 EtherCAT是运动控制领域使用最广泛的总线通信协议之一。 如果我们只有一台电脑&#xff0c;能不能直接控制EtherCAT总线伺服呢&#xff1f; 这个是完全可以的。 我们可以在电脑上安装实时运行环境&#xff0c;从而实现对伺服电机的总…...

vue2制作长方形容器,正方形网格散点图,并且等比缩放拖动

需求&#xff1a;有个长方形的容器&#xff0c;但是需要正方形的网格线&#xff0c;网格线是等比缩放的并且可以无线拖动的&#xff0c;并且添加自适应缩放和动态切换&#xff0c;工具是plotly.js,已完成功能如下 1.正方形网格 2.散点分组 3.自定义悬浮框的数据 4.根据窗口大小…...

鸿蒙-页面和自定义组件生命周期

页面生命周期&#xff0c;即被Entry装饰的组件生命周期&#xff0c;提供以下生命周期接口&#xff1a; onPageShow&#xff1a;页面每次显示时触发一次&#xff0c;包括路由过程、应用进入前台等场景。onPageHide&#xff1a;页面每次隐藏时触发一次&#xff0c;包括路由过程、…...

AD域学习

AD域学习 AD域一、什么是AD域二、概念三、疑问四、内容4.1、AD域的功能 五、应用实践 AD域 一、什么是AD域 AD域&#xff08;Active Directory Domain&#xff09;是微软Windows网络中的一个概念&#xff0c;它是一种计算机网络的形式&#xff0c;其中所有用户账户、计算机、…...

leetcode 3066. 超过阈值的最少操作数 II 中等

给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。 一次操作中&#xff0c;你将执行&#xff1a; 选择 nums 中最小的两个整数 x 和 y 。将 x 和 y 从 nums 中删除。将 min(x, y) * 2 max(x, y) 添加到数组中的任意位置。 注意&#xff0c;只有当 nums 至少包含两个元…...

使用 WPF 和 C# 绘制覆盖网格的 3D 表面

此示例展示了如何使用 C# 代码和 XAML 绘制覆盖有网格的 3D 表面。示例使用 WPF 和 C# 将纹理应用于三角形展示了如何将纹理应用于三角形。此示例只是使用该技术将包含大网格的位图应用于表面。 在类级别&#xff0c;程序使用以下代码来定义将点的 X 和 Z 坐标映射到 0.0 - 1.…...

大数据学习(34)-mapreduce详解

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…...

源码编译安装httpd 2.4

方法一&#xff1a; 1、下载 Apache 源代码&#xff1a; wget https://archive.apache.org/dist/httpd/httpd-2.4.54.tar 2、解压源代码&#xff1a; tar -zxvf httpd-2.4.54.tar.gz 3、进入源代码目录&#xff1a; cd httpd-2.4.54 4、安装开发工具组&#xff1a; yum…...

1.15寒假作业

web&#xff1a;nss靶场ez_ez_php 打开环境&#xff0c;理解代码 使用个体传参的方法&#xff0c;首先代码会检查file参数的前三个字符是不是php&#xff0c;如果是就输出nice&#xff0c;然后用include函数包含file&#xff0c;绕过不是则输出hacker&#xff0c;如果没有file…...

Java中private和static同时使用会出现什么情况?

引言 这几天在学习单例设计模式&#xff08;后面会出一期包含23种设计模式介绍的博客&#xff09;的时候发现了一段代码 private static Single single; 当时我就在想&#xff0c;这个private和static一起用的话外界想要访问这个成员变量到底是能不能访问到呢&#xff1f;当…...

vue倒计时组件封装,根据每个循环项的倒计时是否结束添加新类名。

1.创建countdown.vue文件&#xff1a; <template><p style"font-size: 10px">{{time}}</p> </template> <script>export default{data () {return {time : ,flag : false}},mounted () {let time setInterval(() > {if (this.fla…...

nvim 打造成可用的IDE(2)

上一个 文章写的太长了&#xff0c; 后来再写东西 就一卡一卡的&#xff0c;所以新开一个。 主要是关于 bufferline的。 之前我的界面是这样的。 这个图标很不舒服有。 后来发现是在这里进行配置。 我也不知道&#xff0c;这个配置 我是从哪 抄过来的。 测试结果&#xff1…...

Spring Boot教程之五十五:Spring Boot Kafka 消费者示例

Spring Boot Kafka 消费者示例 Spring Boot 是 Java 编程语言中最流行和使用最多的框架之一。它是一个基于微服务的框架&#xff0c;使用 Spring Boot 制作生产就绪的应用程序只需很少的时间。Spring Boot 可以轻松创建独立的、生产级的基于 Spring 的应用程序&#xff0c;您可…...

目标检测跟踪中的Siamese孪生网络与普通卷积网络(VGG、ResNet)有什么区别?

1、什么是Siamese网络&#xff1f; Siamese网络又叫孪生网络&#xff0c;是一种特殊的神经网络架构&#xff0c;由一对&#xff08;或多对&#xff09;共享参数的子网络组成&#xff0c;用于学习输入样本之间的相似性或关系。最早在 1994 年由 Bromley 等人提出&#xff0c;最…...

AIGC时代 | 探索AI Agent的奥秘:四种设计模式引领未来智能趋势

AIGC时代 | 探索AI Agent的奥秘&#xff1a;四种设计模式引领未来智能趋势 引言 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;AI Agent作为新一代的智能代理&#xff0c;正在引领工作流程的革新。AI Agent&#xff0c;即人工智能代理&#xff0c;是一种…...

PyTorch框架——基于深度学习YOLOv5神经网络水果蔬菜检测识别系统

基于深度学习YOLOv5神经网络水果蔬菜检测识别系统&#xff0c;其能识别的水果蔬菜有15种&#xff0c;# 水果的种类 names: [黑葡萄, 绿葡萄, 樱桃, 西瓜, 龙眼, 香蕉, 芒果, 菠萝, 柚子, 草莓, 苹果, 柑橘, 火龙果, 梨子, 花生, 黄瓜, 土豆, 大蒜, 茄子, 白萝卜, 辣椒, 胡萝卜,…...

【redis】redis-cli命令行工具的使用

redis-cli命令行工具是一个功能强大的Redis客户端&#xff0c;它允许用户与Redis数据库进行交互和管理。 以下是一些常用参数的使用说明&#xff1a; 基本连接参数 -h, --host <hostname>&#xff1a;指定要连接的Redis服务器的主机名或IP地址。如果未指定&#xff0c;…...

阿里云-Centos9-安装Docker-配置镜像拉取加速地址-开机自启

阿里云-Centos9-安装Docker-配置镜像拉取加速地址-开机自启 更新镜像源安装环境配置加速卸载安装pull拉取加速开机自启 更新镜像源 # dnf update&#xff1a;更新所有已安装的软件包。 sudo dnf update -y安装环境 # 安装环境 # yum-utils&#xff1a;提供了管理yum仓库的工具。…...

Grails应用http.server.requests指标数据采集问题排查及解决

问题 遇到的问题&#xff1a;同一个应用&#xff0c;Spring Boot(Java)和Grails(Groovy)混合编程&#xff0c;常规的Spring Controller&#xff0c;可通过Micromete Pushgateway&#xff0c; 采集到http.server.requests指标数据&#xff0c;注意下面的指标名称是点号&#…...

使用 WPF 和 C# 将纹理应用于三角形

此示例展示了如何将纹理应用于三角形,以使场景比覆盖纯色的场景更逼真。以下是为三角形添加纹理的基本步骤。 创建一个MeshGeometry3D对象。像往常一样定义三角形的点和法线。通过向网格的TextureCoordinates集合添加值来设置三角形的纹理坐标。创建一个使用想要显示的纹理的 …...