C++奇迹之旅:深入理解赋值运算符重载

请添加图片描述

文章目录

  • 📝赋值运算符重载
  • 🌠 运算符重载
    • 🌉特性
  • 🌠 赋值运算符重载
  • 🌠传值返回:
  • 🌠传引用赋值:
    • 🌉两种返回选择
    • 🌉赋值运算符只能重载成类的成员函数不能重载成全局函数
  • 🚩总结


📝赋值运算符重载

🌠 运算符重载

运算符重载是C++中的一个重要特性,他允许我们为自定义的类型定义自己的运算符行为。通过运算符重载,我们可以使用与内置数据类型相同的语法来操作自定义类型,从而提高代码的可读性和可维护性

还是我们熟悉的日期函数:

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

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	// 给缺省值
	int _year = 1;
	int _month = 1;
	int _day = 1;
};

然后我们定义两个日期对象d1和d2:

int main()
{
	Date d1(2024, 2, 17);
	Date d2(2024, 6, 27);
	
	return 0;
}

当你想要比较两个对象d1和d2的数据是否一样,这是通常的比较方法:
创建一个专门的比较函数来比较两个Date对象是否相同。

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

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

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

int main()
{
	Date d1(2024, 2, 17);
	Date d2(2024, 6, 27);
	
	if (d1.isSame(d2))
	{
		cout << "d1 and d2 are the same date" << endl;
	}
	else
	{
		cout << "d1 and d2 are different dates" << endl;
	}

	return 0;
}

很明显的可以看出这是个比较函数,能不能直接通过像内置类型那样d1==d2来比较相同呀,因此运算符重载就来了:
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通函数类似

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

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

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

//private:
	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;
}
int main()
{
	Date d1(2024, 2, 17);
	Date d2(2024, 6, 27);
	
	//d1.isSame(d2)
	if (d1 == d2)
	{
		cout << "d1 and d2 are the same date" << endl;
	}
	else
	{
		cout << "d1 and d2 are different dates" << endl;
	}

	return 0;
}

这样使用运算符重载是不是直接可以使用d1==d2,方便了,但是这里有个注意点:此时bool operator==(const Date& d1,const Date& d2)这个函数我是写在全局变量中,因此private也去掉,才能够访问。

这样一来,安全性降低了,可读性升高了,有点得不偿失,运算符重载成全局的就需要成员变量是公有的,那么问题来了,封装性如何保证?
在这里插入图片描述
补充:两种调用方式直接写和显示调用是一样的:

int main()
{
	Date d1(2024, 2, 17);
	Date d2(2024, 6, 27);

	// 显式调用
	operator==(d1, d2);
	
	// 直接写,装换调用,编译会转换成operator==(d1, d2);
	d1 == d2;

	return 0;
}

两者的call指令是一样的:
在这里插入图片描述
bool operator==(const Date& d1, const Date& d2) 重载成全局,无法访问私有成员,解决办法有三种:

  1. 使用 getter 和 setter 函数的方案:
class Date
{
public:
    Date(int year = 1900, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }

    int GetYear() { return _year; }
    int GetMonth() { return _month; }
    int GetDay() { return _day; }

    void SetYear(int year) { _year = year; }
    void SetMonth(int month) { _month = month; }
    void SetDay(int day) { _day = day; }

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

private:
    int _year;
    int _month;
    int _day;
};
  1. 使用友元函数的方案:
    • 这种方式可以直接访问私有成员变量,不需要额外的 getter 和 setter 函数。
    • 但是,将 operator== 函数声明为友元函数会破坏类的封装性,需要谨慎使用。
class Date
{
    friend bool operator==(const Date& d1, const Date& d2);

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

private:
    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. 重载为成员函数的方案:
    • 这是最常见和推荐的方式。
class Date
{
public:
    Date(int year = 1900, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    
    // bool operator==(Date* this, const Date& d2)
    // 这里需要注意的是,左操作数是this,指向调用函数的对象
    bool operator==(const Date& d) 
    {
        return _year == d._year 
        	&& _month == d._month 
        	&& _day == d._day;
    }

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

这里我们本节主要学习第三种重载为成员函数的方案:bool operator==(const Date& d) 这里需要注意的是,左操作数是this,指向调用函数的对象。
这里的参数使用const修饰,确保传入的原对象不被修改

函数的调用方法:

int main()
{
	Date d1(2024, 2, 17);
	Date d2(2024, 6, 27);
	
	//显示调用
	d1.operator==(d2);

	//转换调用,等价与d1.operator==(d2);
	d1 == d2;

	
	cout << d1.operator==(d2) << endl;
	cout << (d1 == d2) << endl;
	//注意这里的()括号,因为符号优先级问题
	return 0;
}

在这里插入图片描述

对于自定义对象我们可以使用运算符,返回值是根据运算符来决定,加减返回int类型,判断大小,使用bool类型:一个类要重载哪些运算符是看需求,看重载有没有价值和意义

🌉特性

  1. 不能通过连接其他符号来创建新的操作符:比如operator@
  2. 重载操作符必须有一个类类型参数
  3. 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  4. 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐
    藏的this
  5. .* :: sizeof ?: . 注意以上5个运算符不能重载。这个经常在笔试选择题中出
    现。
    这里主要注意的是.*,看看这个代码:
class OB
{
public:
	void func()
	{
		cout << "void func" << endl;
	}
};

typedef void(OB::*ptrFunc)();//成员函数指针类型

int main()
{
	//函数指针
	//void(*ptr)();

	//成员函数要加&才能取到函数指针
	ptrFunc fp = &OB::func;//定义函数指针fp指向func

	OB temp;//定义OB类对象temp

	(temp.*fp)();

	return 0;
}

首先这是普通函数指针的定义:

//函数指针
void(*ptr)();

其次是成员函数指针类型:

typedef void(OB::*ptrFunc)();//成员函数指针类型

在这个代码中,typedef void(OB::*ptrFunc)() 定义了一个新的类型 ptrFunc,它是一个指向 OB 类的成员函数的指针类型。

  1. void(OB::*)()

    • 这是一个函数指针类型,它指向一个返回值为 void 且没有参数的成员函数。
    • OB::* 表示这个函数指针是指向 OB 类的成员函数。
  2. typedef void(OB::*ptrFunc)();

    • 使用 typedef 关键字定义了一个新的类型 ptrFunc
    • ptrFunc 就是这个指向 OB 类成员函数的指针类型的别名。

这样定义之后,我们就可以使用 ptrFunc 这个类型来声明指向 OB 类成员函数的指针变量了。

//成员函数要加&才能取到函数指针
	ptrFunc fp = &OB::func;//定义函数指针fp指向func

main() 函数中,我们使用 &OB::func 获取了 OB 类的 func() 成员函数的地址,并将其赋值给 ptrFunc 类型的变量 fp

	OB temp;//定义OB类对象temp
	(temp.*fp)();

然后,我们创建了一个 OB 类的对象 temp。最后,使用 (temp.*fp)(); 语法调用了 temp 对象的 func() 成员函数。这里的 .* 运算符用于通过成员函数指针调用成员函数。

🌠 赋值运算符重载

在这里插入图片描述

上节我们学了拷贝构造来进行数据的复制:一个已经存在的对象,拷贝给另一个要创建初始化的对象

Date d1(2024, 4, 20);
// 拷贝构造
// 一个已经存在的对象,拷贝给另一个要创建初始化的对象
Date d2(d1);
Date d3 = d1;

当然那还有赋值拷贝/赋值运算符重载也可以进行复制:
一个已经存在的对象,拷贝赋值给另一个已经存在的对象

Date d1(2024, 4, 20);
d1 = d4;

在这里插入图片描述

这里是单个赋值,能不能连续像内置类型那样赋值?
	int i, j, k;
	i = j = k = 1;

连续赋值的本质是:从右向左开始,1赋值给k,k=1表达式返回值为左操作数k,接着j赋值给k,j=k表达式返回值为左操作数,再接着i就拿到了1,连续赋值完毕。

同理,自定义类型也是一样的,有两种方式传值和引用:

🌠传值返回:

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

		return *this;
	}

由于每次返回的都是左操作数,我们需要this,但是这是传值返回,返回的是this的临时拷贝,不是这个函数里局部变量*this

class Date
{
public:
	Date(int year = 1900, 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 = d4;
	// ->d2 = d4
	// ->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, 4, 14);

	// 拷贝构造
	// 一个已经存在的对象,拷贝给另一个要创建初始化的对象
	Date d2(d1);
	Date d3 = d1;

	Date d4(2024, 5, 1);

	// 赋值拷贝/赋值重载
	// 一个已经存在的对象,拷贝赋值给另一个已经存在的对象
	d1 = d4;

	d1 = d2 = d4;

	return 0;
}

当从右向左开始,d4赋值给d2d2=d4表达式返回值为左操作数d2,这里的d2*this,但是传值返回,会生成一个临时的拷贝,返回的是Date *this,此时此刻,如果你一步一步调试,他会跳转到Date的构造函数里Date(const Date& d),然后刷新private的值,然后进行第二步的连续赋值d2赋值给d1,和上面的步骤是一样的。

🌠传引用赋值:

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

		return *this;
	}

这里按引用传递,无需再创造临时变量拷贝,再调用拷贝构造函数,当从右向左开始,d4赋值给d2d2=d4表达式返回值为左操作数d2,这里的d2*this,*this直接返回的是左操作数的d2的别名。

这里还需注意的一点是,我们可能会出现写错,避免不必要的操作:比如自赋值

d1=d1

处理自赋值问题主要有以下几个原因:

  1. 如果不检查自赋值的情况,当执行d1 = d1时,会进行不必要的赋值操作。这可能会造成性能的浪费,尤其是对于大型对象而言。
  2. 某些情况下,对象的成员变量可能依赖于其他成员变量的值。如果在赋值过程中,这些成员变量的值被覆盖,可能会导致对象处于不一致的状态,从而引发错误。

修改自赋值问题:使用地址来判断

Date& operator=(const Date& d)
{
	if (this != &d)//使用的是地址判断
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	return *this;
}

因此我们总结一下赋值运算符重载格式

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

🌉两种返回选择

  1. 传值返回
Date func()
{
	Date d(2024, 4, 14);
	return d;
}

int main()
{
	const Date& ref = func();

	return 0;
}

选择传值,还是传引用呢?

class Date
{
public:
	Date(int year = 1900, 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 = d4;
	// d2 = d4
	// d1 = d2
	// Date operator=(const Date& d)
	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;
	}

	~Date()
	{
		cout << "~Date()" << endl;
		_year = -1;
		_month = -1;
		_day = -1;
	}

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

Date func()
{
	Date d(2024, 4, 14);
	return d;
}

int main()
{
	const Date ref = func();

	return 0;
}

在这里插入图片描述

  1. 传引用返回
Date& func()
{
	Date d(2024, 4, 14);
	return d;
}

int main()
{
	const Date& ref = func();

	return 0;
}

在这里插入图片描述

总结一下:返回对象是一个局部对象或者临时对象,出了当前func函数作用域,就析构销毁了,那么不能用引用返回用引用返回是存在风险的,因为引用对象在func函数栈帧已经销毁了
虽然引用返回可以减少一次拷贝,但是出了函数作用,返回对象还在,才能用引用返回

理解了func函数,那么operator=重载赋值函数返回选择哪种方式也是同样的方法:
*thisd2,在main函数传参的时候,this指针是存放栈空间的,当operator函数生命周期结束时,*this回到的是回到的是main函数的,也就是*this离开operator时生命周期未到,不会析构,因此按引用返回。
在这里插入图片描述

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

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 =”必须是非静态成员

原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。
在这里插入图片描述
用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。

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;
}

既然编译器生成的默认赋值运算符重载函数已经可以完成字节序的值拷贝了,还需要自己实现吗?当然像日期类这样的类是没必要的。那么下面的类呢?验证一下试试?

// 这里会发现下面的程序会崩溃掉?这里就需要我们以后讲的深拷贝去解决。
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;
	s2 = s1;
	return 0;
}

直接无法加载发生异常!
在这里插入图片描述
注意:如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必须要实现。
在这里插入图片描述


🚩总结

请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用Gold-yolo模块改进yolov8模型

gold-yolo论文&#xff1a; https://arxiv.org/pdf/2309.11331.pdf gold-yolo代码&#xff1a; https://github.com/huawei-noah/Efficient-Computing/tree/master/Detection/Gold-YOLO 一 gold模块简介 Gold-Yolo是华为诺亚方舟实验室2023年发布的工作&#xff0c;主要优化检…

Linux程序的地址空间,进程终止

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 算法 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂 一.程序的地址空间 1.1程序的地址空间的引入 我们知道frok可以创建…

重塑我们对随机性在计算中的作用的理解

2023年图灵奖&#xff0c;最近刚刚颁给普林斯顿数学教授 Avi Wigderson&#xff01;作为理论计算机科学领域的领军人物&#xff0c;他对于理解计算中的随机性和伪随机性的作用&#xff0c;作出了开创性贡献。 Avi Wigderson 的履历 自 1999 年以来&#xff0c;Wigderson 一直担…

Python五子棋VS人机对战

上一次编写了一个python五子棋游戏,但是属于玩家之间的对战。今天介绍五子棋和人机对战。本博文目的是教学和一些毕业设计。 目前电脑下棋逻辑算法还是比较简单的,不能和市面上五子棋相提并论,请大家理想对待! 代码: import pygame import sys import tkinter as tk fro…

再拓信创版图-Smartbi Insight V11与东方国信CirroData数据库完成兼容适配认证

近日&#xff0c;思迈特商业智能与数据分析软件 [简称&#xff1a;Smartbi Insight] V11与北京东方国信科技股份有限公司 &#xff08;以下简称东方国信&#xff09;CirroData-OLAP分布式数据库V2.14.1完成兼容性测试。经双方严格测试&#xff0c;两款产品能够达到通用兼容性要…

python语言零基础入门——注释、print()函数、input()函数

目录 一、注释 1.块注释 2.行内注释 3.多行注释 二、打印变量 1.print()函数&#xff1a;输出/打印指定内容 2.input()函数&#xff1a;输入指定内容 三、编程题&#xff1a;个人名片 一、注释 1.块注释 以#开始&#xff0c;直到本行结束都是注释为了保证代码的可读性…

初步学习node.js文件模块

环境已安装好&#xff1b; 写一个read1.js如下&#xff1b; var fs require("fs"); var data ;// 创建一个流 var stream1 fs.createReadStream(test1.jsp); stream1.setEncoding(UTF8);// 绑定data事件 stream1.on(data, function(mydata) {data mydata; });/…

Unity ECS

一&#xff1a;前言 ECS与OOP不同&#xff0c;ECS是组合编程&#xff0c;而OOP的理念是继承 E表示Entity&#xff0c;每个Entity都是一个有唯一id的实体。C表示Component&#xff0c;内部只有属性&#xff0c;例如位置、速度、生命值等。S表示System&#xff0c;驱动实体的行为…

Leetcode. 12 整数转罗马数字

罗马数字包含以下七种字符&#xff1a; I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例…

原来我一直被骗了!Burp suite诱导劫持攻击【附工具】

一、点击劫持 点击劫持是一种基于界面的攻击&#xff0c;用户通过点击诱饵网站中的一些其他内容被诱骗点击隐藏网站上的可操作内容。举例来说&#xff0c;一个网络用户可能会访问一个诱饵网站&#xff08;可能是通过电子邮件提供的链接&#xff09;&#xff0c;并点击一个按钮以…

C语言---贪吃蛇(二)---逻辑和代码的实现

文章目录 前言1.准备工作2.蛇的相关属性3.游戏流程设计3.1.游戏开始(GameStart)3.1.1.设置光标位置3.1.2.隐藏光标3.1.3.打印欢迎界面3.1.4.创建地图3.1.5.初始化蛇身3.1.6.创建食物 3.2.游戏运行(GameRun)3.2.1.打印信息栏3.2.2.蛇身的移动3.2.2.1.判断下一个结点是否为食物3.…

【Linux】iptables的应用

iptables 防火墙 防火墙是一种网络安全系统&#xff0c;它位于内部网络与外部网络&#xff08;如互联网&#xff09;之间&#xff0c;通过实施预定义的安全策略来控制网络间的通信。防火墙的主要目标是保护内部网络资源免受未经授权的访问、攻击或潜在威胁&#xff0c;同时允…

FFmpeg源码编译

msys2 依赖环境安装 依赖环境安装编译X264编译 fdk-aac文件处理编译x265编译FFmpeg 依赖环境安装 编译X264 用于h264 AVC视频格式编码 CCcl ./configure --enable-shared #指定使用cl,编译成动态链接库 make -j32 #使用32线程进行编码 make install命令一 关于第一条命令执…

VUE的import store from ‘./vuex/store改为‘ import store from ‘./vuex/store.js‘

ERROR Failed to compile with 1 error 下午5:25:40 error in (webpack)-dev-server/client?http://10.18.173.180:8081/sockjs-node Syntax Error: no such file or directory, open D:\4myroom\H…

2024年,新手做抖店千万犯这几点错误,轻则保证金,重则封店!

哈喽~我是电商月月 很多做抖音小店的新手朋友都忽略了违规操作这一部分&#xff0c;交完保证金以为后续不开了保证金还能退回&#xff1f;别天真了&#xff01; 不了解抖音小店的行为规则&#xff0c;违规了不仅保证金没了&#xff0c;严重的话&#xff0c;店铺都开不下去&am…

【精简改造版】大型多人在线游戏BrowserQuest服务器Golang框架解析(2)——服务端架构

1.架构选型 B/S架构&#xff1a;支持PC、平板、手机等多个平台 2.技术选型 &#xff08;1&#xff09;客户端web技术&#xff1a; HTML5 Canvas&#xff1a;支持基于2D平铺的图形引擎 Web workers&#xff1a;允许在不减慢主页UI的情况下初始化大型世界地图。 localStorag…

谷雨,春天的最后一次回眸

人生并不像火车要通过每个站似的经过每一个生活阶段。 今日谷雨&#xff0c;这不是技术文&#xff0c;是码哥的碎碎念 谷雨猕漫着芭蕉的味道动了心成了情白素贞的姻以伞结缘可天若无雨地上无伞断桥未断过客&#xff0c;能留下一段传奇吗&#xff1f;或许难难 倘若在江城边不是西…

盲人购物指南:智能化辅助引领超市购物新体验

作为一名资深记者&#xff0c;我有幸见证了一位盲人朋友借助一款名为蝙蝠避障的高科技辅助应用&#xff0c;独立完成超市购物之旅&#xff0c;这一过程充分展示了盲人购物指南新时代的到来。 在前往超市的路上&#xff0c;这款应用犹如一位贴心的“电子向导”&#xff0c;实时为…

编程范式之函数编程

文章目录 **核心概念****特征****优点****示例语言**案例 函数编程&#xff08;Functional Programming, FP&#xff09;是一种编程范式&#xff0c;它强调程序由一系列不可变的值和纯函数&#xff08;Pure Function&#xff09;组成&#xff0c;尽量避免副作用&#xff08;Sid…

Zynq7000系列中PL时钟使用

可编程逻辑&#xff08;PL&#xff09;具有自己的时钟管理生成和分配功能&#xff0c;并从处理器系统&#xff08;PS&#xff09;中的时钟发生器接收四个时钟信号&#xff08;如图25-10所示&#xff09;。 在嵌入式系统中&#xff0c;PL时钟的管理和分配对于确保逻辑电路的正确…
最新文章