拷贝构造,赋值运算符重载(六千字长文详解!)

news2024/11/25 22:57:16

c++之类和对象详解 拷贝构造,赋值运算符重载

文章目录

  • c++之类和对象详解 拷贝构造,赋值运算符重载
    • 拷贝构造
      • 拷贝构造特征
        • 拷贝构造的注意
    • 赋值运算符重载
      • 运算符重载
    • 赋值重载
      • 赋值运算符的写法注意
      • 赋值重载的默认性
      • 赋值重载和拷贝赋值的区别在哪里?

拷贝构造

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

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

构造——初始化

拷贝构造——拷贝初始化

class Date
{
    //....
};

int main()
{
    Date d1(2000, 1, 1);
    Date d2(d1);//以d1的数据来初始化d2
    return 0;
}

拷贝构造特征

拷贝构造函数也是特殊的成员函数,其特征如下:

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

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

    为什么会引发无穷递归引用呢?

    class Date
    {
    public:
        Date(const Date& d)
        {
            cout << "拷贝构造成功!" << endl;
            _year = d._day;
            _month = d._month;
            _day = d._day;
        }
        Date(int year, int month = 1, int day = 1)
        {
            _year = year; 
            _month = month;
            _day = day;
        }
    private:
        int _year = 0;
        int _month = 0;
        int _day = 0;
    };
    void func1(Date d)//形参是实参的拷贝
    {
        cout << "func1" << endl;
    }
    void func2(Date& d)//形参是实参的别名
    {
        cout << "func2" << endl;
    }
    int main()
    {
        Date d1(2000, 1, 1);
        func1(d1);
        func2(d1);
        return 0;
    }
    

    image-20221004190955449.png

    我们可以看到传值引用导致产生的临时变量进行拷贝时候会引发拷贝构造

    假如我们使用的是传值引用来当拷贝构造的参数:

    拷贝构造函数接收值需要创建临时变量!创建临时变量引发拷贝构造,然后拷贝构造又需要创建临时变量去接收值,那么临时变量的临时变量又引发拷贝构造…以此不断的递归下去!

    image-20221004192520191.png

    所以只能使用引用,因为引用是取别名实际用的仍然是那个变量!

    为什么要使用拷贝构造这个东西呢?

    因为自定义类型可能很复杂!编译器不清楚应该按什么方式拷贝!

    像是内置类型编译器可以直接按字节一个个拷贝!

    但是像是链表或者树呢?

    像是链表我们就要一个个拷贝!

    像是树我们就得递归拷贝!

    先是拷贝根再拷贝左子树,然后拷贝右子树

    然后一直递归下去!

    那能不呢使用指针呢?答案是可以的!==因为指针的类型是date 产生的临时变量不会引发拷贝构造,但是这时候叫做构造函数,不是拷贝构造函数!==,==因为拷贝构造的定义就是参数类型要是类的引用!==但是那样子很不方便还要解引用等操作,不如使用引用!*

    拷贝构造的注意

    为了防止反向拷贝的情况发生我们一般都会加上const缩小权限!

    Date(Date& d)
    {
        _year = d._day;
        _month = d._month;
        d._day = _day;
    }//没有加上const会导致反向拷贝使原先数据丢失!
    Date(const Date& d)
    {
        _year = d._day;
        _month = d._month;
        d._day = _day;
    }//这样的话一旦发生反向拷贝就会直接报错!
    
  3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

    注意:在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定 义类型是调用其拷贝构造函数完成拷贝的。

    class Date
    {
    public:
    	//Date(Date& d)
    	//{
    	//    _year = d._day;
    	//    _month = d._month;
    	//    _day = d._day;
    	//}
    	Date(int year, int month = 1, int day = 1)
    	{
    		_year = year;
    		_month = month;
    		_day = day;
    	}
    private:
    	int _year = 0;
    	int _month = 0;
    	int _day = 0;
    };
    int main()
    {
    	Date d1(2000, 1, 1);
    	Date d2(d1);
    	return 0;
    }
    
    

    image-20221004195654913.png

    我们可以看到对于日期类这种只含内置类型的,编译器自动生成的默认拷贝构造函数已经够用了!

    但是像是更复杂就会出问题

    class stack
    {
    public:
    	stack(int newcapcacity = 4)
    	{
    		int* temp = (int*)malloc(sizeof(int) * newcapcacity);
    		if (temp == nullptr)
    		{
    			perror("malloc fail");
    			exit(-1);
    		}
    		_a = temp;
    		_top = 0;
    		_capacity = newcapcacity;
    	}
    	~stack()//这就是栈的析构函数!
    	{
    		free(_a);
    		_a = nullptr;
    		_top = 0;
    		_capacity = 0;
    	}
    	void Push(int x)
    	{
    		if (_top == _capacity)
    		{
    			int newcapacity = 2 * _capacity;
    			int* temp = (int*)realloc(_a, sizeof(int) * newcapacity);
    			if (temp == nullptr)
    			{
    				perror("realloc fail");
    				exit(-1);
    			}
    			_a = temp;
    			_capacity = newcapacity;
    		}
    		_a[_top++] = x;
    	}
    private:
    	int* _a;
    	int _top;
    	int _capacity;
    };
    int main()
    {
    	stack st1;
    	st1.Push(1);
    	st1.Push(2);
    	stack st2(st1);
    return 0;
    }
    
    

    image-20221004200501190.png

    看上去好像是完成了拷贝!但是有没有发现st1和st2的指针指向了同一块内存空间,也就是意味着我 改变st1就会改变st2!

    这个程序会导致崩溃!因为当st2的指针被析构函数释放掉之后,st1的析构函数就会导致访问野指针!

    image-20221004201133716.png

    image-20221004203353541.png

    所以此时我们需要使用到深拷贝!

    
    class stack
    {
    public:
    	stack(int newcapcacity = 4)
    	{
    		int* temp = (int*)malloc(sizeof(int) * newcapcacity);
    		if (temp == nullptr)
    		{
    			perror("malloc fail");
    			exit(-1);
    		}
    		_a = temp;
    		_top = 0;
    		_capacity = newcapcacity;
    	}
    	~stack()
    	{
    		free(_a);
    		_a = nullptr;
    		_top = 0;
    		_capacity = 0;
    	}
    	stack(stack& st)//深拷贝
    	{
    		_a = (int*)malloc(sizeof(int) * st._capacity);
    		if (_a == nullptr)
    		{
    			perror("malloc fail");
    			exit(-1);
    		}
    		memcpy(_a, st._a, st._top * sizeof(int));
    		_capacity = st._capacity;
    		_top = st._top;	
    	}
    	void Push(int x)
    	{
    		if (_top == _capacity)
    		{
    			int newcapacity = 2 * _capacity;
    			int* temp = (int*)realloc(_a, sizeof(int) * newcapacity);
    			if (temp == nullptr)
    			{
    				perror("realloc fail");
    				exit(-1);
    			}
    			_a = temp;
    			_capacity = newcapacity;
    		}
    		_a[_top++] = x;
    	}
    private:
    	int* _a;
    	int _top;
    	int _capacity;
    };
    int main()
    {
    	stack st1;
    	st1.Push(1);
    	st1.Push(2);
    	stack st2(st1);
    	st2.Push(3);
     return 0;
    }
    

    image-20221004204849048.png

    这下就成功完成了深拷贝

    需要写析构函数的类的都要写拷贝构造!

    不需要写析构的类都不需要自己写!

    像是栈,链表,顺序表,二叉树…这些要动态开辟的都需要写析构函数,也都需要写拷贝构造!

    但是像是日期类的这些就不需要!

    class stack
    {
    //....
    };
    
    class MyQuene
    {
    public:
    	void Push(int x)
    	{
    		_PushST.Push(x);
    	}
    private:
    	stack _PopST;
    	stack _PushST;
    };
    
    

    image-20221004210348724.png

    像是myqueue这种也都不需要写拷贝构造!因为它也不需要写析构函数!

  4. 拷贝构造函数典型调用场景:

    1. 使用已存在对象创建新对象
    2. 函数参数类型为类类型对象
    3. 函数返回值类型为类类型对象

赋值运算符重载

class Date
{
public:
	Date(Date& d)
	{
	    _year = d._day;
	    _month = d._month;
	    _day = d._day;
	}
	Date(int year, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year = 0;
	int _month = 0;
	int _day = 0;
};
int main()
{
	Date d1(2000, 1, 1);
	Date d2(2000, 2, 28);
    d1 > d2;
    d1 == d2;
    d1 + 100;
    d1 - d2;
	return 0;
}

像是上面的d1与d2我们如何简洁的进行比较呢?如何像是以前一样使用运算符?这时候就引入了运算符重载!

运算符重载

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

为了让自定义类型可以使用运算符!

函数名字为:关键字operator后面接需要重载的运算符符号。 函数原型:返回值类型 operator操作符(参数列表)

class Date
{
public:
	Date(Date& d)
	{
	    _year = d._day;
	    _month = d._month;
	    _day = d._day;
	}
	Date(int year, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	bool operator==(const Date& d2)
	{
		return _year == d2._year
			&& _day == d2._day
			&& _month == d2._month;
	}
private:
	int _year = 0;
	int _month = 0;
	int _day = 0;
};
int main()
{
	Date d1(2000, 1, 1);
	Date d2(2000, 2, 28);
    d1 == d2;//此时编译器会转换成调用d1.operator==(d2);
    d1.operator==(d2);//直接这样调用也行!
    
    //编译器很聪明如果是放在全局的那么会优先调用全局,如果全局没有就回去类里面找!
   //如果是全局就会被转换成operator==(d1,d2)
	cout << (d1 == d2) << endl;//要加括号因为运算符优先级问题,因为我们并没有重载<< 所以<< 没哟办法输出自定义类型!
	return 0;
}


为什么运算符重载在要放在类里面呢?

因为如果我们放在外面会导致一个问题,那就是因为类里面的数据都是私有的!

我们无法访问,如果想要访问我们只能再写一个函数用于获取类里面的数据!

所以不如直接放在里面!

bool operator==(const Date& d1,const Date& d2)
{
	return d1._year == d2._year
		&& d1._day == d2._day
		&& d1._month == d2._month;
}//这样写会显示参数哦多为什么?
//因为类里面的非静态成员函数都会加上一个this指针!
//也就是说是实际上的样子为
bool operator==(cosnt* Date this,const Date& d1,const Date& d2)
{
	return d1._year == d2._year
		&& d1._day == d2._day
		&& d1._month == d2._month;
}//所以实际上我们只需要自己写一个参数就足够了!
bool operator==(const Date& d2)
{
	return _year == d2._year
		&& _day == d2._day
		&& _month == d2._month;
}

赋值重载

	Date& operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;
	};//这就是赋值重载

赋值运算符的写法注意

    void operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

如果怎么写的话会出现一个问题就是在无法进行链式访问
d1 = d2 = d3;

image-20221009162352128.png

但是也最好不要使用Date作为返回类型因为这样子会产生一个临时变量!

	Date operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;
	};

因为d在出了作用域后不会被销毁可以使用引用来作为返回值!

使用引用作为传参的类型 也是为了防止产生临时变量!const是为了防止对传参对象进行修改!

以引用作为返回值的时候要注意不可以传参对象作为返回值

	Date& operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return d;
	}

image-20221009162855054.png

这样就会出现经典的权限放大!

解决方法

    cosnt Date& operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return d;
	}
// or
    Date& operator=(Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return d;
	}

但是这样也要求我们得使用const的类型去接收,我们一般要求变量都是可以修改的!

所以还是使用Date&

如果使用第二种修改方式这样也会导致我们无法对传参对象进行保护!

    Date& operator=(Date& d)
	{
		d._year = _year;//万一写反了!
		_month = d._month;
		_day = d._day;
		return d;
	}

赋值重载的默认性

如果我们不写一个赋值重载,类中会自己生成一个赋值重载!

class Date
{
public:
	Date(int year = 10,int month = 10,int day = 10)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//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(100,10,100);
	Date d2;
	d2 = d1;

	return 0;
}

image-20221009164113277.png

默认的赋值重载会完成一次直拷贝!按字节一个个的拷贝过去!

默认赋值重载和默认拷贝构造很相似

  1. 对于内置类型都是进行值拷贝!
  2. 对于自定义类型都是调用自定义类型的默认成员函数!

默认赋值重载调用自定义类型的默认赋值重载

默认拷贝构造调用自定义类型的默认拷贝构造!

所以对于默认拷贝构造的问题也会出现在默认赋值重载上面

像是对于要动态开辟的类型 例如stack/queue/list…

class stack
{
public:
	stack(int newcapcacity = 4)
	{
		int* temp = (int*)malloc(sizeof(int) * newcapcacity);
		if (temp == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
		_a = temp;
		_top = 0;
		_capacity = newcapcacity;
	}
	~stack()//这就是栈的析构函数!
	{
		free(_a);
		_a = nullptr;
		_top = 0;
		_capacity = 0;
	}
	stack(stack& st)
	{
		_a = (int*)malloc(sizeof(int) * st._capacity);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
		memcpy(_a, st._a, st._top * sizeof(int));
		_capacity = st._capacity;
		_top = st._top;
	}
	void Push(int x)
	{
		if (_top == _capacity)
		{
			int newcapacity = 2 * _capacity;
			int* temp = (int*)realloc(_a, sizeof(int) * newcapacity);
			if (temp == nullptr)
			{
				perror("realloc fail");
				exit(-1);
			}
			_a = temp;
			_capacity = newcapacity;
		}
		_a[_top++] = x;
	}
private:
	int* _a;
	int _top;
	int _capacity;
};
int main()
{
	stack st1;
	st1.Push(1);
	st1.Push(2);
	stack st2;
	st2.Push(3);
	st2.Push(4);
	st1 = st2;
	return 0;
}

image-20221009164858218.png

然后这个程序会发生崩溃!

因为两个指针指向了同一块的内存地址!

image-20221009170008562.png

st2的析构函数释放了这一块内存空间

然后st1的析构函数又一次的释放了这一块内存空间!

释放野指针导致了崩溃!

而且还会导致内存泄漏!

因为st的指针指向了st2的空间,但是却没有释放自己原有的空间!

所以要自己去写赋值重载!

	stack& operator=(const stack& st)
	{
		free(_a);
		_a = (int*)malloc(sizeof(int) * st._capacity);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit;
		}
		memcpy(_a, st._a, sizeof(int) * _top);
		_top = st._top;
		_capacity = st._capacity;
        return *this;
	}

image-20221010122506260.png

这样子就可以完成对于栈这种类型的赋值

但是这样写还是有缺陷!比如遇到自己赋值给自己的时候!

image-20221010122824188.png

我们会发现原本的值竟然变成的随机值!

因为我们一开始就free掉了原来的空间!所以导致了一旦自己赋值给自己的时候,一开始的free就会导致数据的丢失!

所以我们要进一步的修改

	stack& operator=(stack& st)
	{
		if (this != &st)
		{
			_a = (int*)malloc(sizeof(int) * st._capacity);
			if (_a == nullptr)
			{
				perror("malloc fail");
				exit(-1);
			}
			memcpy(_a, st._a, st._top * sizeof(int));
			_capacity = st._capacity;
			_top = st._top;
		}
		return *this;
	}

为什么不使用realloc去改变原来的数组大小,反倒是使用先free再malloc的形式呢?

答:因为要考虑的情况太多了,数组比原来大,数组比原来小,数组和原来相同

数组比原来的大我们可以正常使用realloc。

数组比原来小,我们不使用realloc(realloc一般不用于缩小数组!)

但是如果不对数组进行缩小而是正常的进行拷贝,万一出现原先数组有100000个 赋值数组只有10个这种情况的话就会导致极大的空间浪费!

所以基于以上的几种情况我们选择采用先free在malloc的方式!

我们从上面的特征可以看出来拷贝构造和赋值重载具有很多的相似之处!

我们也可以得出一个相似的结论:

需要写析构函数的就要写显性赋值重载,否则就不需要!

像是类似myquene的情况因为不用谢析构所以自然也不用谢赋值重载都是显性的都够用了!

因为myqueue的默认赋值重载会自动的去调用stack类型的赋值重载来使用!

class stack
{
    //....
}
class MyQuene
{
public:
	void Push(int x)
	{
		_PushST.Push(x);
	}
private:
	stack _PopST;
	stack _PushST;
};
int main()
{
	MyQuene q1;
	q1.Push(1);
	q1.Push(2);
	MyQuene q2;
	q2.Push(3);
	q2.Push(4);

	q1 = q2;
	return 0;
}

image-20221010124601839.png

赋值重载和拷贝赋值的区别在哪里?

class Date
{
public:
	Date(int year = 10,int month = 10,int day = 10)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	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(100,10,100);
	Date d2(d1);//拷贝构造 是初始化另一个要马上创建的对象!
	d2 = d1;//赋值重载(赋值拷贝!)已经存在的两个对象之间的拷贝!
    
    Date d3 = d1;//这看上去好像是赋值重载!
    //但是其实拷贝构造!因为从定义上看它更符合 初始化一个要创建的对象!
	return 0;
}

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

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

相关文章

Ubuntu问题汇总

1.sudo ifconfig 找不到命令 ubuntu找不到ifconfig_猿 白的博客-CSDN博客_ubuntu ifconfig命令找不到 没有找到ifconfig的命令&#xff0c;需要进行安装&#xff0c;按照提示中的命令安装相关的工具包 sudo apt install net-tools 2.ip查找 3.重启服务器后&#xff0c;nvid…

记一次浏览器预览通过nginx且有权限控制的静态文件

我的需求是&#xff0c;后台生成了合同文件&#xff0c;用户需要进行预览&#xff0c;如果采用流的实现方式的话&#xff0c;会涉及到输入流、输出流&#xff0c;性能开销较大&#xff0c;所以采用的是直接访问文件&#xff0c;这里就涉及到一个问题&#xff0c;就是 需要设置…

Mobtech秒验SDK——一站式解决用户登录场景

据悉&#xff0c;北京中文万维科技有限公司旗下多款APP&#xff0c;和MobTech开发的秒验SDK达成合作&#xff0c;为其提供用户一键登录解决方案。 北京中文万维科技有限公司是一家立志以移动互联网阅读为发展起点的阅读互动娱乐高新技术企业&#xff0c;旗下拥有多款阅读类APP。…

互动教学场景下的视频直播线上研讨会应用(组图)

阿酷TONY / 原创 / 2022-12-14 / 长沙 / 互动教学/互动培训类场景特点&#xff1a; 1. 直播过程中&#xff0c;学员不仅是观看讲师的授课内容&#xff0c;还要与讲师直接进行音视频会话&#xff1b;当然一些非培训教学场景也常用到&#xff0c;比如线上学术类研讨会等等。 2…

【Pycharm教程】 详解 PyCharm Macros宏

宏提供了一种方便的方法来自动化您在编写代码时经常执行的重复过程。您可以录制、编辑和播放宏&#xff0c;为它们分配快捷方式并共享它们。 宏可用于在文件中组合一系列与编辑器相关的操作。 您无法记录按钮单击、导航到弹出窗口以及访问工具窗口、菜单和对话框。 可以使用没…

从3s到40ms,看看人家的性能优化技巧,确实优雅

什么是高性能系统 先理解一下什么是高性能设计&#xff0c;官方定义: 高可用(High Availability&#xff0c;HA)核心目标是保障业务的连续性&#xff0c;从用户视角来看&#xff0c;业务永远是正常稳定的对外提供服务&#xff0c;业界一般用几个 9 来衡量系统的可用性。通常采…

代码随想录算法训练营第五十天|123.买卖股票的最佳时机III、 188.买卖股票的最佳时机IV

123.买卖股票的最佳时机III 此题限定了买卖的次数&#xff0c;所以应该用几个状态来记录所对应得利润 至多买卖两次&#xff0c;这意味着可以买卖一次&#xff0c;可以买卖两次&#xff0c;也可以不买卖。 dp数组及下标含义 一天一共就有五个状态&#xff0c; 0 没有操作 1 第…

java+mysql 基于ssm的驾校预约管理系统

随着现代驾校预约管理的快速发展,可以说驾校预约管理已经逐渐成为现代驾校预约管理过程中最为重要的部分之一。但是一直以来我国传统的驾校预约管理并没有建立一套完善的行之有效的驾校预约管理系统,传统的驾校预约管理已经无法适应高速发展,无论是从效率还是从效果来看都远远的…

代码随想录Day50|123.买卖股票的最佳时机III、188.买卖股票的最佳时机IV

文章目录123.买卖股票的最佳时机III188.买卖股票的最佳时机IV123.买卖股票的最佳时机III 文章讲解&#xff1a;代码随想录 (programmercarl.com) 题目链接&#xff1a;123. 买卖股票的最佳时机 III - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 给定一个数组&…

[附源码]Python计算机毕业设计感动校园人物投稿网站Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

极简入门 2022 docker 部署skywalking9.2.0

安装skywalking服务 官方地址&#xff1a;官网 安装文档&#xff1a;文档地址 拉取镜像 docker pull apache/skywalking-oap-server:9.2.0 docker pull apache/skywalking-ui:9.2.0运行skywalking-oap容器 docker run --name skywalking-oap -e TZAsia/Shanghai -p 12800:1…

ffmpeg的基本用法

title: ffmpeg的基本用法 categories:[ffmpeg] tags:[音视频编程] 一、ffmpeg的安装 1.Centos安装 FFmpeg 在默认的CentOS 8 源仓库中没有提供。你可以选择通过源文件编译安装 FFmpeg&#xff0c;或者使用dnf工具从Negativo17源仓库中安装。我们将会使用第二个选项。 完成…

正大期货数据整合 新鲜事简单报

本周观察重点: &#x1f539;美国11月CPI数据昨晚公布为7.1%&#xff0c;低于市场预期7.3%&#xff0c;较于前值7.7%大幅回落&#xff0c;随通膨回落&#xff0c;静待联准会未来货币政策方向。 12/15 (四) 美国、香港、欧洲、英国、台湾央行12月利率决策会议 12/16 (六) 日本、…

基于java+springboot+mybatis+vue+mysql的小学家校一体作业帮

项目介绍 本系统采用java语言开发&#xff0c;后端采用springboot框架&#xff0c;前端采用vue技术&#xff0c;数据库采用mysql进行数据存储。系统功能如下&#xff1a; 前台&#xff1a; 首页、微社区、试卷、公告通知、个人中心、后台管理 后台&#xff1a; 首页、个人中…

SpringCloud02

1.Nacos配置管理 Nacos除了可以做注册中心&#xff0c;同样可以做配置管理来使用。 1.1.统一配置管理 当微服务部署的实例越来越多&#xff0c;达到数十、数百时&#xff0c;逐个修改微服务配置就会让人抓狂&#xff0c;而且很容易出错。我们需要一种统一配置管理方案&#xff…

技术分享 | 软件项目管理与跨部门沟通协作

项目管理是在项目活动中运用知识、技能、工具和方法&#xff0c;以便达到项目要求。 软件项目管理有其特定的对象、范围和活动&#xff0c;着重关注成本、进度、风险和质量的管理&#xff0c;还需要协调开发团队和客户的关系&#xff0c;协调内部各个团队之间的关系&#xff0…

怎么把pdf格式转成word文档?如何将 PDF 转换为 Word

怎么把pdf格式转成word文档&#xff1f;PDF是运用得很广泛地的办公文档&#xff0c;但是不能编辑&#xff0c;为了方便编辑&#xff0c;需要将PDF转换为word&#xff0c;那么&#xff0c;如何将 PDF 转换为 Word&#xff0c;下面&#xff0c;易我小编会讲解实用的pdf转word的操…

基于VBA实现电缆结构自动出图(二) —— 单芯线

大家敢相信吗&#xff0c;原来VBA竟然可以实现电缆结构自动出图&#xff0c;换句话说&#xff0c;只要输入数据&#xff0c;VBA会自动将电缆的结构画出来&#xff0c;同时还可以渲染&#xff0c;结果竟然不输画图软件&#xff0c;真真让我刮目相看。这里我就不过多介绍VBA了&am…

传奇登录器列表显示不连接

传奇登录器列表显示不连接 我们打开登录器后列表显示不连接怎么办&#xff1f; 图中有打码部分望读者理解&#xff08;平台gz&#xff09; 以下我们大家说下几种列表显示不连接的几种情况 第一种&#xff1a;列表格式错误 在我们开区的位置默认是127.0.0.1 端口默认7000 如果…

Django captcha验证码应用【亲测可用】

1、下载captcha安装包&#xff1a; pip install django-simple-captcha pip3 install pillow -i Simple Index 2、在settings的INSTALLED_APPS添加: captcha&#xff0c; 3、在控制台执行&#xff1a; 生成迁移文件&#xff1a;python3 manage.py makemigrations 迁移文件…