模板与STL(C++)

news2024/9/25 13:24:29

  • 七、模板与STL(泛型编程)
    • 7.1 模板的概念
    • 7.2 函数模板
      • 7.2.1 函数模板的定义
      • 7.2.2 函数模板的实例化
      • 7.2.3 模板参数
      • 7.2.4 函数模板的特化
    • 7.3 类模板
      • 7.3.1 类模板的定义
      • 7.3.2 类模板实例化
      • 7.3.3 类模板特化

七、模板与STL(泛型编程)

模板(template)是C++实现代码重要机制的重要工具,是泛型技术(即与数据类型无关的通用程序设计技术)的基础。模板表示的是概念级的通用程序设计方法,它把算法和数据类型区分开来,能够设计出独立于具体数据类型的模板程序,模板程序能以数据类型为参数生成针对于该类型的实际程序代码。模板分为函数模板和类模板两类,ANSI标准C++库就是使用模板技术实现的。

7.1 模板的概念

某些程序除了所处理的数据类型之外,程序代码和程序功能相同,但为了实现他们,却不得不编写多个与具体数据类型紧密结合的程序,例如

int Min(int a, int b){
    return a<b?a:b;
}
float Min(float a, float b){
    return a<b?a:b;
}
double Min(double a, double b){
    return a<b?a:b;
}
char Min(char a, char b){
    return a<b?a:b;
}

如何简化以上编程呢?C语言中,可以通过宏的方式实现以上想法:

#define Min(a,b) ((a) < (b))?(a):(b)

C++中,也可以利用宏来进行类似程序设计,但宏避开了C++类型检查机制,在某些情况下可能引发错误,是不安全的。更好的方法就是模板来实现这样的程序设计。

C++中的模板与制作冰糕的模具很相似,是生产函数或类的模具。模板接收数据类型参数,并根据此类型创建相应的函数或类。

对于上面的所有Min()而已,只需要下面的函数模板就能够生成所有的Min()函数。

template <typename T>
T Min(T a, T b){
    return a<b?a:b;
}

template和typenae是用来定义模板的关键字。min模板不涉及任何具体的数据类型,而是用T代表任意数据类型,称为类型参数。Min模板代表了求两个数据最小的通用算法,它与具体数据类型无关,但能够生成计算各种具体数据类型的最小值的函数。编译器的做法是用具体的类型替换模板中的类型参数T,生成具体类型的函数Min()。比如用int替换掉模板中的所有T就能生成求两个int类型数据的函数min()。

#include <iostream>
using namespace std;

/*
int Min(int a, int b){
    return a<b?a:b;
}
float Min(float a, float b){
    return a<b?a:b;
}
double Min(double a, double b){
    return a<b?a:b;
}
char Min(char a, char b){
    return a<b?a:b;
}
*/

template <typename T>
T Min(T a, T b){
	return a<b?a:b;
}

int main(void){

	int i = 4, j = 8;
	char i2 = '4', j2 = '3';

	cout << Min(i, j) << endl;
	cout << Min(i2, j2) << endl;
	return 0;
}

从函数模板Min可以看成,C++模板提供了对逻辑结构相同的数据对象通用行为的定义方法,它把通用算法的实现和具体的数据类型区分开来,模板操作的是参数化的数据类型(类型参数)而非实际数据类型。一个带有类型参数的函数称为函数模板,带有类型参数的类型称为模板类

在调用模板时,必须为它的类型参数提供实际数据类型,C++将用该数据类型替换模板中的全部类型参数,由编译器生成与具体的数据类型相关的运行的程序代码,这个过程称为模板的实例化。由函数模板实例化生成的函数称为模板函数,由类模板实例化生成的类称为模板类

在这里插入图片描述

7.2 函数模板

函数模板提供了一种通用的函数行为,该函数行为可以用多种不同的数据类型进行调,编译器会根据调用类型自动将它实例化为具体数据类型的函数代码,也就是说函数模板代表了一个函数家族。与普通函数相比,函数模板中某些函数元素的数据类型是未确定的,这些元素的类型将在使用时被参数化;与重载函数相比,函数模板不需要程序员重复编写函数代码,它可以自动生成许多功能相同单参数和返回值类型不同的函数。

7.2.1 函数模板的定义

template <typename T1, typename T2, ...>
返回类型 函数名(参数表){
	... ...
}

template是模板定义的关键字写在<>中的T1 T2…是模板参数中的typename表示其后的参数可以是任意类型的。

#include <iostream>
using namespace std;

/*
int Min(int a, int b){
    return a<b?a:b;
}
float Min(float a, float b){
    return a<b?a:b;
}
double Min(double a, double b){
    return a<b?a:b;
}
char Min(char a, char b){
    return a<b?a:b;
}
*/

template <typename T>
T Min(T a, T b){
	return a<b?a:b;
}

int main(void){

	int i = 4, j = 8;
	char i2 = '4', j2 = '3';

	cout << Min(i, j) << endl;
	cout << Min(i2, j2) << endl;
	return 0;
}

7.2.2 函数模板的实例化

当编译器遇到关键字template和跟随其后的参数定义时,它只是简单地知道这个函数模板在后面的程序代码中可能会用到。除此之外,编译器并不会做额外的工作。在这个阶段函数模板本身并不能使编译器产生任何代码,因为编译器此时并不知道函数模板要处理的具体数据类型,根本无法生成任何函数代码。

当编译器此时并不知道函数模板要处理的具体数据类型,根本无法生成任何函数代码。

当编译器遇到程序中对函数模板的调用时,它才会根据调用语句中实参的具体类型,确定模板参数的数据类型,并用此类型替换函数模板的模板参数,生成能够处理该类型的函数代码,即模板函数。

对于7.2.1代码可以执行一下命令观察实验效果。

nm a.out | grep a.out
image-20240106154551306

7.2.3 模板参数

  • 模板参数的匹配问题

    C++在实例化函数模板的过程中,只是简单地将模板参数替换为实参的类型,并以此生成模板函数,不会进行参数类型的任何转换。这种方式与普通函数的参数处理有着极大的区别,以前在普通函数的调用过程中,会进行参数的自动类型转换。

    #include <iostream>
    using namespace std;
    
    double Max(double a, double b) {
    	return a>b?a:b;
    }
    
    int main(void) {
    	
    	double a = 2, b = 3.14;
    	float c = 4.6, d = 5.7;
    
    	cout << "2 3.14 : " << Max(a,b) << endl;
    	cout << "2 4.6 : " << Max(a,c) << endl;
    	cout << "2 100 : " << Max(a,100) << endl;
    	return 0;
    }
    

    以上程序能够正确执行,现在使用函数模板来实现通用的功能,如下所示

    #include <iostream>
    using namespace std;
    
    template <typename T>
    T Max(T a, T b){
    	return a>b?a:b;
    }
    
    int main(void) {
    	
    	double a = 2, b = 3.14;
    	float c = 4.6, d = 5.7;
    
    	cout << "2 3.14 : " << Max(a,b) << endl;
    	cout << "2 4.6 : " << Max(a,c) << endl;
    	cout << "2 100 : " << Max(a,100) << endl;
    	return 0;
    }
    

    编译以上程序,产生模板参数不匹配的错误。产生这个错误的原因是模板实例化过程中不会进行任何的参数类型转换。编译器在翻译Max(a,c)时,由于实参类型为double和float,而Max函数模板只有一个形参类型T,总不能让T同时取double和float两种类型吧?要知道模板实例化过程中,C++不会进行任何形式的隐式类型转换,于是产生了上述编译错误。

    这种问题的解决方式有:

    • 在模板调用时进行参数类型的强制转换

      cout << "2 4.6 : " << Max(a,double(c)) << endl;
      cout << "2 100 : " << Max(a,double(100) << endl;
      
    • 显示指定函数模板实例化的类型参数

      	cout << "2 4.6 : " << Max<double>(a,c) << endl;
      	cout << "2 100 : " << Max<double>(a,100) << endl;
      
    • 指定多个模板参数

      在模板函数的调用过程中,为了避免出现一个模板参数与多个调用实参的类型冲突问题,可以为函数模板指定多个不同的类型参数。

      #include <iostream>
      using namespace std;
      
      template <typename T1, typename T2>
      T1 Max(T1 a, T2 b){
      	return a>b?a:b;
      }
      
      int main(void) {
      	
      	double a = 2, b = 3.14;
      	float c = 4.6, d = 5.7;
      
      	cout << "2 3.14 : " << Max(a,b) << endl;
      	cout << "2 4.6 : " << Max(a,c) << endl;
      	cout << "2 100 : " << Max(a,100) << endl;
      	return 0;
      }
      
    • 模板函数的形参表

      不要误以为函数模板中的参数只能是类型形参,它也可以包括普通类型的参数。

      #include <iostream>
      using namespace std;
      
      template <typename T>
      void display(T &arr, unsigned int n){
      
      	for(int i = 0; i < n; i++){
      		cout << arr[i] << "\t" ;
      	}
      	cout << endl;
      }
      
      int main(void) {
      	
      	int a[] = {1,2,3,4,5,6,7,8};
      	char b[] = {'a','b','c','d','e','f'};
      
      	display(a, sizeof(a)/sizeof(a[0]));
      	display(b, sizeof(b)/sizeof(b[0]));
      	return 0;
      }
      //输出结果
      myubuntu@ubuntu:~/lv19/cplusplus/dy08$ ./a.out 
      1	2	3	4	5	6	7	8	
      a	b	c	d	e	f	
      

7.2.4 函数模板的特化

在某些情况下,函数模板并不能生成处理特定数据类型的模板函数,上面例子中的Max函数模板可以计算int 或者 char 类型数据的最大值,但对于字符串类型却是无能为力的。解决这类问题的方法就是对函数模板进行特化。所谓特化,就是针对模板不能处理的特殊数据类型,编写与模板同名的特殊函数专门处理这些数据类型。语法格式如下所示。

template<>
返回类型 函数名<特化的数据类型>(参数表){
    ...
}

例如:

#include <iostream>
#include <cstring>
using namespace std;

template <typename T> //函数模板
T Min(T a, T b){
	return a>b?a:b;
}

template <> //特化版 函数模板
const char* Min(const char* a, const char* b){

	cout << "Min(const char*, const char*)" << endl;
	return (strcmp(a,b) > 0)?b:a;
}

int main(void) {
	
	cout << Min('a', 'b') << endl;
	cout << Min("aaa", "aaa") << endl;
	return 0;
}
//输出结果
myubuntu@ubuntu:~/lv19/cplusplus/dy08$ ./a.out 
b
Min(const char*, const char*)
aaa

7.3 类模板

函数模板用于设计程序代码相同而所处理的数据类型不同的通用函数。与此类似,C++也支持用类模板来设计结构和成员函数完全相同,但所处理的数据类型不同的通用类。比如,对于堆栈类而言,可能存在整数栈、双精度栈、字符栈等多种不同数据类型的栈,每个栈除了所处理的数据类型不同之外,类的结构和成员函数完全相同,可为了在非模板的类设计中实现这些栈,不得不重复编写各个栈类的相同代码,例如初始化栈、入栈、出栈等操作。为了解决该问题,C++中用类模板设计这样的类簇最方便,一个类模板就能够实例化生成所需要的栈类。

类模板也称为类属类,它可以接收类型为参数,设计出与具体类型无关的通用类。在设计类模板时,可以使其中的某些数据成员,成员函数的参数或返回值与具体类型无关。

7.3.1 类模板的定义

类模板与函数模板的定义形式类似,如下所示:

template <typename T1, typename T2, ...>
class 类名{
    ...
}

实例:设计一个栈的类模板Stack,在模板中使用类型参数T表示栈中存放的数据,用非类型参数MAXSIZE代表栈的大小。

vi Stack.cpp
#include <iostream>
using namespace std;

template <typename T, int MAXSIZE>
class Stack{
private:
	T elements[MAXSIZE]; //类型不确定 所以写 T
	int top; //栈顶
public:
	Stack():top(0){
	}
	void push(T e);
	T pop();

	bool empty(){
		return top == 0;
	}
	bool full(){
		return top==MAXSIZE;
	}
};

template <typename T, int MAXSIZE>
void Stack<T, MAXSIZE>::push(T e){
	if(full()) {
		cout << "Stack is full, can not push" << endl;
	}
	elements[top++] = e;
}

template <typename T, int MAXSIZE>
T Stack<T, MAXSIZE>::pop() {
	if(top == 0) {
		cout << "stack is empty, can not pop" << endl;
	}
	top--;
	return elements[top];
}
int main(void){
    return 0;
}

7.3.2 类模板实例化

类模板的实例化包括模板实例化和成员函数实例化。当用类模板定义对象时,将引起类模板的实例化。在实例化模板时,如果模板参数就是类型参数,则必须为它指定具体的类型;如果模板参数是非类型参数,则必须为它指定一个常量值。如对前面的Stack类模板而言,下面是他的一条实例化语句:

Stack<int, 10> istack;

编译器实例化Stack的方法是:将Stack模板声明中的所有的类型参数T替换为int,将所有的非类型参数MAXSIZE替换为10,这样就用Stack模板生成了一个int类型的模板类。为了区别于普通类,暂且将该类记作Stack<int, 10>,即在类模板后面的一对<>中写上模板参数。该类的代码如下:

class Stack{
private:
	int elements[10]; // MAXSIZE 替换为 10 , T类型 替换为 int
	int top; //栈顶
public:
	Stack():top(0){
	}
	void push(int e);
	int pop();

	bool empty(){
		return top == 0;
	}
	bool full(){
		return top==MAXSIZE;
	}
};

最后C++用这个模板类定义一个对象istack.

注意:在上面的实例化过程中,并不会实例化模板的成员函数,也就是说,在用类模板定义对象时并不会生成类成员函数的代码。类模板成员函数的实例化发生在该成员函数被调用时,这就以为着只有那些被调用的成员才会被实例化。或者说,只有当成员函数被调用了,编译器才会为它生成真正的代码。

#include <iostream>
using namespace std;

template <typename T, int MAXSIZE>
class Stack{
private:
	T elements[MAXSIZE]; //类型不确定 所以写 T
	int top; //栈顶
public:
	Stack():top(0){
	}
	void push(T e);
	T pop();

	bool empty(){
		return top == 0;
	}
	bool full(){
		return top==MAXSIZE;
	}
};

template <typename T, int MAXSIZE>
void Stack<T, MAXSIZE>::push(T e){
	if(full()) {
		cout << "Stack is full, can not push" << endl;
	}
	elements[top++] = e;
}

template <typename T, int MAXSIZE>
T Stack<T, MAXSIZE>::pop() {
	if(top == 0) {
		cout << "stack is empty, can not pop" << endl;
	}
	top--;
	return elements[top];
}

int main(void) {
	Stack<int, 10> istack;

	istack.push(11); //此处调用该成员函数 编译器才会生成成员函数模板
	//cout << istack.pop() << endl;
	return 0;
}

可以将pop函数的类外定义删除掉,然后再编译运行程序,可以发现的是程序依然能够正确的执行。

与普通类的对象一样,类模板的对象或引用也可以作为函数的参数,只不过这类函数通常是模板函数,且其调用实参常常是该类模板的模板类对象。

#include <iostream>
using namespace std;

template <typename T, int MAXSIZE>
class Stack{
private:
	T elements[MAXSIZE]; //类型不确定 所以写 T
	int top; //栈顶
public:
	Stack():top(0){
	}
	void push(T e);
	T pop();

	bool empty(){
		return top == 0;
	}
	bool full(){
		return top==MAXSIZE;
	}
};

template <typename T, int MAXSIZE>
void Stack<T, MAXSIZE>::push(T e){
	if(full()) {
		cout << "Stack is full, can not push" << endl;
	}
	elements[top++] = e;
}

template <typename T, int MAXSIZE>
T Stack<T, MAXSIZE>::pop() {
	if(top == 0) {
		cout << "stack is empty, can not pop" << endl;
	}
	top--;
	return elements[top];
}

template <typename T>
void display(Stack<T, 10> &s){
	while(!s.empty()){
		cout << s.pop() << endl;
	}
}

int main(void) {
	Stack<int, 10> istack;

	istack.push(11);
	istack.push(12);
	istack.push(123);
	istack.push(886);

	display(istack);
	return 0;
}
//输出结果
myubuntu@ubuntu:~/lv19/cplusplus/dy08$ ./a.out 
886
123
12
11

7.3.3 类模板特化

类模板代表了一种通用程序设计的方法,它表示了无限类集合,可以实例化生成基于任何类型的模板类。在通常情况下,由类模板生成的模板类都能够正常的工作,但也有类模板生成的模板类代码对某些数据类型不适用的情况。

如:设计一个通用数组类,它能够直接存取数组元素,并能够输出数组中的最小值。

#include <iostream>
using namespace std;

template <typename T>
class Arr{
private:
	T *arr;
	int size;
public:
	Arr(int size=10){
		this->size = size;
		arr = new T;
	}
	~Arr(){
		delete arr;
	}
	T &operator[](int i);
	T Min();
};

template <typename T>
T& Arr<T>::operator[](int i){
	if(i < 0 || i > size-1){
		cout << "数组下标越界" << endl;
	}
	return arr[i];
}

template <typename T>
T Arr<T>::Min() {

	T temp;
	temp = arr[0];
	for(int i=1; i < size; i++){
		if(temp > arr[i])
			temp = arr[i];
	}
	return temp;
}

int main(void) {
	Arr<int> a(5);

	for(int i=0; i < 5; i++){
		a[i] = 68+i;
	}
	cout << a.Min() << endl;

	Arr<char *> b(5);
	b[0] = (char *)"ffs";
	b[1] = (char *)"ees";
	b[2] = (char *)"dds";
	b[3] = (char *)"ccs";
	b[4] = (char *)"bbs";
	cout << b.Min() << endl;
	return 0;
}
//输出结果
myubuntu@ubuntu:~/lv19/cplusplus/dy08$ ./a.out 
68
ffs
*** Error in `./a.out': free(): invalid next size (fast): 0x0924d018 ***
Aborted (core dumped)

显然Arr类模板并不完全适用于生成char *类型的模板类,因为Arr类模板的Min成员函数并使用于字符指针类型的计算大小。

解决上述问题的方法就是类模板特化,即用与该模板相同的名字为某种数据类型专门重新一个模板类。特化类模板时,可以随意增减和改写模板原有的成员,成员函数的改写也不受任何限制,可以与原来的成员函数变得完全不同。

类模板有两种特化方式,一种是特化整个类模板,另一种是特化个别成员函数。前者是为某种类型单独建立一个类,后者则只针对特化的数据类型提供个别成员函数的实现代码,特化后的成员函数不再是一个模板函数,而是针对特点类型的普通函数。

与函数模板特化方式相同,类模板成员函数的特化也以templat<>开头。形式如下:

template<>
返回类型 类模板名<特化的数据类型>:: 特化成员函数名(参数表){
    ...
}

Arr类模板对char * 类型来说,除了Min成员函数不适用外,其余成员都可以,则针对char * 类型重新编写Min成员函数,即特例Arr类模板的Min成员函数就能够解决字符串求大小的问题。特化的Min函数如下:

template<>
char * Arr<char *>::Min(){
	char *temp;
	temp = arr[0];
	for(int i=1; i < size; i++){
		if(strcmp(temp, arr[i]) > 0)
			temp = arr[i];
	}
	return temp;
}

为了某种数据类型特化整个类模板也要以template<> 开头,形式如下所示:

template<> class 类模板名<特化的数据类型>{
    ...
}

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

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

相关文章

获得利润和成长,应采取什么步骤, 澳福认为只需坚持一点

大多数交易者通常会考虑在外汇交易中获取利润&#xff0c;但只有少数人会思考这样一个问题:为了获得利润和专业成长&#xff0c;应该采取什么步骤。像“外汇交易怎么赢利”这样的文章很受市场欢迎&#xff0c;但是很少有人在交易中使用这些文章中给出的建议&#xff0c;因为在生…

python设计模式有哪几种

Python 中常见的设计模式有以下几种 一 单例模式&#xff08;Singleton Pattern&#xff09;&#xff1a;确保一个类只有一个实例&#xff0c;并提供全局访问点。 二 工厂模式&#xff08;Factory Pattern&#xff09;&#xff1a;使用工厂方法来创建对象&#xff0c;而不是直…

InternLM第4次课笔记

XTuner 大模型单卡低成本微调实战 1 Finetune介绍 2 XTuner介绍 XTuner中微调的技术&#xff1a; 3 8GB显卡玩转LLM 4 动手实战环节

Vmware虚拟机问题解决方案 运行虚拟机系统蓝屏 运行虚拟机时报错VT-x

1. 运行虚拟机系统蓝屏 可能的原因有两个: 1). 虚拟机所在磁盘的空间不足 ; -------> 清理磁盘空间 。 2). 操作系统版本高, 需要适配新版本的Vmware ; ------> 卸载Vmware15版本, 安装Vmware16版本 。 2. 卸载Vmware步骤 1). 卸载已经安装的VMware 弹出确认框, 点击…

解决“Ubuntu系统与windows系统之间不能执行复制粘贴”之问题

在win11中&#xff0c;发现“Ubuntu系统与windows系统之间不能互相复制粘贴”&#xff0c;只能通过“FPT客户端FileZilla”才能交换文件&#xff0c;但遇到字符串&#xff0c;就没法实现了&#xff0c;因此&#xff0c;在两个系统之间实现互相复制和粘贴字符串&#xff0c;就很…

绘图工具用的好,头发掉的少

程序员不管是在学习&#xff0c;还是工作过程中&#xff0c;很多时候都需要画图&#xff0c;如产品分析、架构设计、方案选型等&#xff0c;良好的绘图不仅可以让绘图者的思路清晰&#xff0c;也可以让聆听者更好的理解。用好画图&#xff0c;升职加薪少不了&#xff01;今天介…

爬虫案例—表情党图片data-src抓取

爬虫案例—表情党图片data-src抓取 表情党网址&#xff1a;https://qq.yh31.com 抓取心情板块的图片data-src 由于此页面采用的是懒加载技术&#xff0c;为了节省网络带宽和减轻服务器压力。不浏览的图片&#xff0c;页面不加载&#xff0c;统一显示LOADING…。如下图&#x…

C++学习笔记——继承和动态内存分配

目录 一、继承 二、动态内存分配 三、继承的细节 四、动态内存分配细节 五、一个动物园管理系统 继承和动态内存分配是C中两个重要的概念 一、继承 继承是C中面向对象编程的一个重要特性&#xff0c;它允许我们创建一个新类&#xff0c;该类从现有的类中继承属性和方法&…

多区域isis配置实验

一、预习&#xff1a; IS-IS&#xff1a;Intermediate System to Intermediate System&#xff0c;中间系统到中间系统&#xff0c;是ISO为它的CLNP&#xff08;ConnectionLess Network Protocol&#xff09;设计的一种动态路由协议&#xff0c;后来为了提供对IP路由的支持&…

Kali安装Xrdp结合内网穿透实现无公网ip远程访问系统桌面

文章目录 前言1. Kali 安装Xrdp2. 本地远程Kali桌面3. Kali 安装Cpolar 内网穿透4. 配置公网远程地址5. 公网远程Kali桌面连接6. 固定连接公网地址7. 固定地址连接测试 前言 Kali远程桌面的好处在于&#xff0c;它允许用户从远程位置访问Kali系统&#xff0c;而无需直接物理访…

设置ubuntu命令行样式

目录 一、脚本 二、含义 三、颜色设置 四、展示 五、注意 上次为了学习ros安装了一个22.04并且做了简单的配置&#xff0c;这次我们进一步对命令行样式进行配置 ubuntu22.04安装与配置_ubuntu22.04硬件配置-CSDN博客 一、脚本 这是他的默认配置&#xff0c;太长了&#x…

开源 UI 组件库和开发工具库概览 | 开源专题 No.59

ant-design/ant-design Stars: 87.9k License: MIT Ant Design 是一个企业级 UI 设计语言和 React UI 库。 为 Web 应用程序设计的企业级 UI。提供一套高质量的开箱即用的 React 组件。使用可预测静态类型编写 TypeScript 代码。包含完整的设计资源和开发工具包。支持数十种语…

【Databend】行列转化:数据透视和逆透视

文章目录 数据准备数据透视数据逆透视总结 数据准备 学生学科得分等级测试数据如下&#xff1a; drop table if exists fact_suject_data; create table if not exists fact_suject_data (student_id int null comment 编号,subject_level varchar null comment …

web3d-three.js场景设计器-sprite广告牌

three.js使用Sprite精灵实现文字或者图片广告牌1.将文字绘制到Canvas&#xff0c;调整对应宽高。2.作为Cavans材质绑定到Sprite3.加载到场景调整适当的scale function createLabel({ text, fontSize, textColor, color, imageUrl }) { return new Promise((resolve, reject) &…

5.3 Verilog 带参数例化

5.3 Verilog 带参数例化 分类 Verilog 教程 关键词&#xff1a; defparam&#xff0c;参数&#xff0c;例化&#xff0c;ram 当一个模块被另一个模块引用例化时&#xff0c;高层模块可以对低层模块的参数值进行改写。这样就允许在编译时将不同的参数传递给多个相同名字的模块…

腾讯云免费服务器怎么申请?腾讯云免费服务器申请难吗?

腾讯云免费服务器申请入口 https://curl.qcloud.com/FJhqoVDP 免费服务器可选轻量应用服务器和云服务器CVM&#xff0c;轻量配置可选2核2G3M、2核8G7M和4核8G12M&#xff0c;CVM云服务器可选2核2G3M和2核4G3M配置&#xff0c;腾讯云服务器网txyfwq.com分享2024年最新腾讯云免费…

Python中使用execfile实现R中的source功能,避免重复加载包导入函数

R中避免重复 在R中要加载多个包&#xff0c;进行全局的配置&#xff0c;定义全局变量&#xff0c;我们可以下一个config.R文件&#xff0c;在分析的代码开头source一下这个config.R文件即可避免每次都要加载包的冗余代码 using是之前定义的一个函数&#xff0c;作用是一次性加…

如何异地链接Pycharm服务器进行远程开发并实现与公司服务器资源同步

文章目录 一、前期准备1. 检查IDE版本是否支持2. 服务器需要开通SSH服务 二、Pycharm本地链接服务器测试1. 配置服务器python解释器 三、使用内网穿透实现异地链接服务器开发1. 服务器安装Cpolar2. 创建远程连接公网地址 四、使用固定TCP地址远程开发 本文主要介绍如何使用Pych…

【数据结构之树和二叉树】

数据结构学习笔记---007 数据结构之树和二叉树概念篇1、树的概念和结构1.1、树的相关概念1.2、树的存储结构 2、二叉树概念及结构2.1、二叉树概念2.2、满二叉树2.3、完全二叉树2.4、满二叉树或完全二叉树的存储形式 3、堆的概念及结构3.1、堆的性质3.2、堆的意义 4、二叉树的存…

考研复试复习-数据库原理(2关系数据库)

一、关系数据模型 1、关系数据结构 (1) 域、笛卡尔积、关系 笛卡尔积实际上可以看成是n个行向量&#xff0c;即&#xff08;域&#xff09;&#xff0c;所组成的一个乘法算式&#xff0c;每一个行向量是一个Di&#xff0c;所有行向量逻辑上组合在一起就是D&#xff0c;就是一…