C++11 新特性 ---- 模板的优化

news2024/11/25 12:36:20
C++11 模板机制:
        ① 函数模板
        ② 类模板
    
    模板的使用:
        ① 范围:模板的声明或定义只能在全局或类范围进行,不可以在局部范围(如函数)
        ② 目的:为了能够编写与类型无关的代码

    函数模板:
        - 格式:
            template <类型形参表或成模板参数列表> //类型函数声明
            返回类型 函数名 (形参表) {
                函数体
            }
        - 注意:
            模板参数表:定义在类或函数定义中用到的类型或值
            类型形参表:可包含基本数据类型和类类型。类型形参需要加class/typename。
                       其中class和typename等价
            T-通用的数据类型,名称可替换,通常为大写
    
    类模板:
        - 格式:
            template <类型形参表> //类型参数声明
            class 类名 {
                类模板的代码
            }
            
            template <类型参数表> //定义在类模板之外的函数必须以关键字template开始
            返回类型 类名 类型名表::成员函数n(形参表)
            {
                成员函数定义体
            }

一、模板的优化

1.模板的右尖括号

/*
    1.模板的右尖括号
*/
#include <iostream>
#include <vector>
using namespace std;

// 类模板Base
template<typename T>
class Base {
public:
    // 遍历容器的操作函数traversal()
    void travelsal(T& t) {
        auto it = t.begin();
        for(;it!=t.end();++it) {
            cout<<*it<<" ";
        }
        cout << endl;
    }
};

int main() {
    vector<int> v{1,2,3,4,5,6,7,8,9};
    Base<vector<int>> b;
    b.travelsal(v);
    return 0;
}

 ① c++98标准下的编译 

g++ -std=c++98 4.模板的优化.cpp -o app

②  c++11标准下的编译 

g++ -std=c++11 4.模板的优化.cpp -o app

 2.默认模板参数

在C++98/03标准中
        ① 类模板可以有默认的模板参数
        ② 不支持函数的默认模板参数

① 在C++98/03标准中,类模板可以有默认的模板参数

#include <iostream>
#include <vector>
using namespace std;
// 2.默认模板参数
/*
    在C++98/03标准中
        ① 类模板可以有默认的模板参数
        ② 不支持函数的默认模板参数
*/
// ① 类模板可以有默认的模板参数
template<typename T=char,T t = 'a'>
class Test{
public:
    void printString() {
        cout<< "current value: " << t <<endl;
    }
};

int main() {
    Test<> t;
    t.printString();
    Test<char,'b'> t1;
    t1.printString();
    return 0;
}

总结: 对于类模板,哪怕所有参数都有默认参数,在使用时也必须在模板名后跟随<>来实例化

② 在C++98/03标准中,不支持函数的默认模板参数

#include <iostream>
#include <vector>
using namespace std;
// 2.默认模板参数
/*
    在C++98/03标准中
        ① 类模板可以有默认的模板参数
        ② 不支持函数的默认模板参数
*/
// ② 不支持函数的默认模板参数
template<typename T=int> // C++98/03不支持这种写法, C++11中支持这种写法
void print(T t) {
    cout<< "current value: " << t <<endl;
}

int main() {
    print(1314);
    return 0;
}

c++11支持对函数模板的默认参数

总结:当所有模板参数都有默认模板,函数模板的调用如同一个普通函数。

③ C++11 结合默认模板参数和模板参数自动推导

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

template<typename R=int,typename N>
R test(N arg) {
    return arg;
}

int main() {
    auto ret1 = test(666);
    cout<<"return value-1: "<<ret1<<endl;//666

    auto ret2 = test<double>(54.321);
    cout<<"return value-2: "<<ret2<<endl;//54.321

    auto ret3 = test<int>(54.321);
    cout<<"return value-3: "<<ret3<<endl;//54

    auto ret4 = test<char,int>(100);
    cout<<"return value-4: "<<ret4<<endl;//d

    return 0;
}

④ C++11 同时使用默认模板参数和模板参数自动推导

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

// 函数的定义
template<typename T,typename U = char>
void func(T arg1 = 99,U arg2 = 99) {
    cout<<"arg1: "<<arg1<<", arg2: "<<arg2<<endl;
}

int main() {
    // 模板函数调用
    func('a');
    func(97,'a');
    // func();//编译报错
    return 0;
}

 func();编译出错是必须确定出T的数据类型,才能使用。

 总结:

① 若可以推导出参数类型,就使用推导出的类型

② 若函数模板无法推导出参数类型,则编译器会使用默认模板参数

③ 若无法推导出模板参数 且 没有设置默认模板参数,编译器会报错

 概括:
 
① 模板参数类型的自动推导是根据模板函数调用时指定的实参进行推导的,无实参则无法推导 

② 模板参数类型的自动推导不会参考函数模板中指定的默认参数

⑥ 函数模板使用时,自动类型推导,必须推导出一直的数据类型T,才可以使用

#include<iostream>
using namespace std;
template<class T>
T add(T a,T b) {
    return a + b;
}

// 1.自动类型推导,必须推导出一致的数据类型T,才可以使用
int main() {
    int a=1;
    int b=2;
    char c='c';
    add(a,b);//正确,可以推导出一致T
    add(a,c);//错误,推导不出一致的T
}

3.类模板

类模板:
    类模板允许用户为类定义一种模式,使得类中的某些数据成员、成员函数的参数或成员函数
    的返回值能取任意类型。类模板的成员函数被认为是函数模板。

    template <类型形参表> //类型参数声明
    class 类名 {
        类模板的代码
    }
    
    template<类型形参表> //定义在类模板之外的函数必须以关键字template开始
    返回类型 类名 类型名表::成员函数n(形参表) {
        成员函数定义体
    }

① 实例化类模板

1.实例化类模板
        ① 类模板不能直接使用,必须先实例化为相应的模板类。
        ② 定义类模板之后,创建模板类:
            类模板名<类型实参表> 对象表;
            类型实参表与类模板中的类型形参表相匹配
#include <iostream>
using namespace std;
/*
    实例化类模板
        ① 类模板不能直接使用,必须先实例化为相应的模板类。
        ② 定义类模板之后,创建模板类:
            类模板名<类型实参表> 对象表;
            类型实参表与类模板中的类型形参表相匹配
*/ 
template<class T1,class T2>
class Student{
public:
    T1 name;//名字
    T2 age;//年龄
    Student(T1 k,T2 v) : name(k),age(v) {}; 
    // 重载操作符:operator ,对小于号< 进行重载
    bool operator < (const Student<T1,T2>& p) const;
};

template<class T1,class T2>
bool Student<T1,T2>::operator < (const Student<T1,T2>& p) const {
    // Pair的成员函数 operator< "小"的意思是关键字小
    return age < p.age;
}

int main() {
    Student<string,int> stu1("Sakura",8);//实例化出一个类Pair<string,int>
    cout <<"My name is " << stu1.name << ",and age is " << stu1.age <<endl;
    Student<string,int> stu2("Luffy",14);//实例化出一个类Pair<string,int>
    cout <<"My name is " << stu2.name << ",and age is " << stu2.age <<endl;
    bool isYoung = stu1.operator<(stu2);
    if(isYoung) {
        cout<<stu1.name<<" is younger than him!!!\n";
    }else {
        cout<<stu2.name<<" is younger than her!!!\n";
    }
    return 0;
}

 

// 2.类模板实例
#include <iostream>
#include <string>
#include <initializer_list>
using namespace std;

template <typename T>
class Array { //类模板
    int size;
    T* p;
public:
    Array();//默认构造函数
    Array(int n);//重载构造函数
    Array(initializer_list<T> lst);
    T& operator[](int) ;//[]重载函数
    int getSize();//获取数组大小
};

// 默认构造函数
template <typename T>
Array<T>::Array() {
    size = 10;
    p = new T[size];
}

// 重载构造函数
template<typename T>
Array<T>::Array(int n) {
    size = n;
    p = new T[size];
}

// 下标运算符重载函数
template<typename T>
T& Array<T>::operator[](int i) {
    if(i>=0 && i<size) {
        return p[i];
    }
}

template<typename T>
Array<T>::Array(initializer_list<T> lst){
    size = lst.end() - lst.begin();
    p = new T[size];
    //cout<<"size大小:"<<size<<endl;
    int k=0;
    for (auto it = lst.begin(); it != lst.end(); ++it)
	{
		//cout<<*it<<endl;
        p[k++] = *it;
    }
    
}

template<typename T>
int Array<T>::getSize(){
    cout<<"获取size:"<<size<<endl;
    return size;
}

int main() {
    Array<int> arr1(2);
    arr1[0] = 520;
    arr1[1] = 1314;
    Array<int> arr2({1,2,3,5});
    
    cout<<"==============打印arr1数组=============="<<endl;
    int size = arr1.getSize();
    for (int i = 0; i < size; i++) {
        cout<<arr1[i]<<" ";
    }
    cout<<endl;

    cout<<"==============打印arr2数组=============="<<endl;
    size = arr2.getSize();
    for (int i = 0; i < size; i++) {
        cout<<arr2[i]<<" ";
    }
    cout<<endl;

    int a=10;int b=20;int c=30;
    cout<<"==============打印arr3数组=============="<<endl;
    Array<int> arr3({a,b,c}); 
    size = arr3.getSize();
    for (int i = 0; i < size; i++) {
        cout<<arr3[i]<<" ";
    }
    cout<<endl;
    return 0;
}

学习initializer_list,可以看这篇博客
C++ 函数传递多参数处理 可变参数模板_c++ 可变参数传递_Mr.禾的博客-CSDN博客icon-default.png?t=N6B9https://blog.csdn.net/qq_24447809/article/details/114793958

#include <iostream>
#include <string.h>
#include <initializer_list>
using namespace std;

template <typename T>
class Array { //类模板
    int size;
    T* p;
public:
    Array();//默认构造函数
    Array(int n);//重载构造函数
    T& operator[](int) ;//[]重载函数
    int getSize();//获取数组大小
};

// 默认构造函数
template <typename T>
Array<T>::Array() {
    size = 10;
    p = new T[size];
}

// 重载构造函数
template<typename T>
Array<T>::Array(int n) {
    size = n;
    p = new T[size];
}

// 下标运算符重载函数
template<typename T>
T& Array<T>::operator[](int i) {
    if(i>=0 && i<size) {
        return p[i];
    }
}

template<typename T>
int Array<T>::getSize(){
    cout<<"获取size:"<<size<<endl;
    return size;
}

class Student {
    
public:
    int no;
    char name[10];
    Student() {}
    Student(int n,const char* s) {
        no = n;
        strcpy(name,s);//使用strcpy为字符串数组赋值
    }
    Student &operator=(Student& s) {//赋值重载构造函数
        no = s.no;
        strcpy(name,s.name);
        return *this;
    }
    void display() {
        cout<<"学号: " << no <<",姓名: "<<name<<endl;
    }
};

int main() {
	cout << "学生列表" << endl;
	Array<Student> arr(4);
    int size = arr.getSize();
	Student x(1, "Tom"), y(2, "Jerry"), z(3, "Sakura");
    Student other = x;

	arr[0] = x; arr[1] = y; arr[2] = z,arr[3] = other;
	for (int i=0;i < size;i++) {
		arr[i].display();
	}
    return 0;
}

 ② 类模板作为函数参数

#include <iostream>
using namespace std;
//类模板作为函数参数
template<class T> 
class A {
    T x;
public:
    A(T a) {
        x = a;
    }
    T abs() {
        if(x<0) return -x;
        else return x;
    }
};

//函数模板中模板类作为形参
template<class T>
void func(A<T> x) {
    cout<<x.abs()<<endl;
}
int main()
{
	//建立对象
	A<int> a(-5);
	A<double> b(-5.8);
	func(a);
	func(b);
 
}

 ③ 函数模板作为类模板的成员

类模板中的成员函数可以是一个函数模板

// 函数模板作为类模板的成员
#include<iostream>
using namespace std;
template<class T>
class A{
public:
    template<class T2>
    void print(T2 t) {cout<<t;}//成员函数模板
};

int main() {
    A<int> a;
    //成员函数模板func被实例化
    a.print('K');     //K
    cout<<endl;
    a.print("hello"); //hello
    cout<<endl;
    a.print(123);     //123
    cout<<endl;
    return 0;
}

④ 类模板中也可以使用非类型参数,即值参数

#include<iostream>
using namespace std;
template<class T,int size>
class A{
public:
    T sum(T a) {
        return a+size;
    }
};

int main(){
    A<char,3> a;
    cout<<a.sum('a')<<endl;// d
    return 0;
}

⑤ 类模板的友元函数

template<class T>
class A{
public:
    T value;
    A() {}
    A(T v):value(v){}
    friend void func1();//与参数类型无关的友元函数
    friend void func2(A<T>& a);//与参数类型有关的友元函数
};

template<class T>
void func1(){
    cout<<"func1"<<endl;
}

template<class T>
void func2(A<T>& a){
    cout<<"func2 value:" <<a.value<<endl;
}

int main() {
    A<double> a(1.2);
    func1<int>();//func1是模板类A<int>的友元函数
    func1<double>();//func1是模板类A<double>的友元函数
    func2<double>(a);//func2是模板类A<double>的友元函数
}

 4.可变参数模板

① 可变参数模板例子

    可变参数模板:
        ① C++11增强了模板功能,允许模板定义中包含0到任意个模板参数
        ② 对参数进行了高度泛化,能表示任意个数,任意类型的参数
        ③ 是一个接收可变数目参数的模板函数或模板类
        ④ 可变数目的参数被称为参数包
    
    语法:
        template<class... T>
        void f(T... args);
    
    声明一个参数包T... args,这个参数包中可以包含0到任意个模板参数
/*
    可变参数模板:
        ① C++11增强了模板功能,允许模板定义中包含0到任意个模板参数
        ② 对参数进行了高度泛化,能表示任意个数,任意类型的参数
        ③ 是一个接收可变数目参数的模板函数或模板类
        ④ 可变数目的参数被称为参数包
    
    语法:
        template<class... T>
        void f(T... args);
    
    声明一个参数包T... args,这个参数包中可以包含0到任意个模板参数
*/
#include <iostream>
#include <map>
using namespace std;
template<typename T,typename... Args>//func是可变参数函数模板 有一个名为T的类型参数和一个名为args的模板参数包
void func(const T&t,const Args&...rest){//func函数列表包含一个const& 类型的参数 指向T的类型,名为rest的函数参数包
    cout<<sizeof...(rest)<<endl;//输出函数参数的数目
};

int main(){
    int a=0;double d=3.14;string str="heheda";
    func(a,str,42,d);//包中有三个参数
	func(str, 42, d);//包中有两个参数
	func(d, str);//包中有一个参数
	func("hi");//空包
    return 0;
}

② 可变参数模板的展开

    可变参数模板的展开:通过展开参数包的方式来获取参数包中的每个参数
    两种展开方式:
        ① 通过递归函数来展开参数包
        ② 通过逗号表达式来展开参数包
/*
    可变参数模板的展开:通过展开参数包的方式来获取参数包中的每个参数
    两种展开方式:
        ① 通过递归函数来展开参数包
        ② 通过逗号表达式来展开参数包
*/
#include <iostream>
using namespace std;
//递归终止函数
void print()
{
   cout << "empty!!!" << endl;
}

//展开函数
template<class T,class... Args>
void print(T head,Args... rest) {
    cout<<"param:"<<head<<endl;
    print(rest...);
}

int main(void)
{
   print(1,2,3,4);
   return 0;
}

③ 可变模板参数求和

#include <iostream>
using namespace std;
template<typename T>
T sum(T t){
    return t;
}
template<typename T, typename ... Types>
T sum (T first, Types ... rest) {
    return first + sum<T>(rest...);
}
int main(void)
{
   cout<<sum(1,2,3,4)<<endl; //10
   return 0;
}

④ 逗号表达式展开参数包

#include <iostream>
using namespace std;

//逗号表达式展开参数包
template <class T>
void printArg(T t)
{
   cout << t << " ";
}
 
template <class ...Args>
void expand(Args... args)
{
   int arr[] = {(printArg(args), 0)...};
}
int main(){
    expand(1,2,3,4);
    cout<<endl;
    return 0;
}

 

  5.可变参数模板类的展开

//前向声明
template<typename... Args> struct Sum;
 
//基本定义
template<typename First, typename... Rest>
struct Sum<First, Rest...>
{
    enum { value = Sum<First>::value + Sum<Rest...>::value };
};
 
//递归终止
template<typename Last>
struct Sum<Last>
{
    enum { value = sizeof (Last) };
};

学习和参考一下文章:

模板的优化 | 爱编程的大丙 (subingwen.cn)icon-default.png?t=N6B9https://subingwen.cn/cpp/template/C++11 模板用法总结_herryone123的博客-CSDN博客icon-default.png?t=N6B9https://blog.csdn.net/kenjianqi1647/article/details/118207899

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

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

相关文章

Glass指纹识别工具,多线程Web指纹识别工具-Chunsou

Glass指纹识别工具&#xff0c;多线程Web指纹识别工具-Chunsou。 Glass指纹识别工具 Glass一款针对资产列表的快速指纹识别工具&#xff0c;通过调用Fofa/ZoomEye/Shodan/360等api接口快速查询资产信息并识别重点资产的指纹&#xff0c;也可针对IP/IP段或资产列表进行快速的指…

chrome插件开发实例05-拦截页面请求

目录 功能 演示 源代码下载 manifest.json devtools.html devtools.js background.js 功能 拦截任意打开页面的请求信息&#xff0c;包括&#xff1a;URL&#xff0c;参数&#xff0c;请求方式method, 返回status&#xff0c;返回体大小&#xff0c;返回原始内容 演示 源…

【工程实践】解决Synonyms无法下载词向量文件

1.前言 使用EDA(Easy Data Augmentation)做数据增强时&#xff0c;需要借助Synonyms库&#xff0c;完成同义词的提取。 Synonyms 是一个中文近义词工具包&#xff0c;它可用于如文本对齐、推荐算法、相似度计算、语义偏移、关键字提取、概念提取、自动摘要、搜索引擎等很多自然…

FFmpeg常见命令行(三):FFmpeg转码

前言 在Android音视频开发中&#xff0c;网上知识点过于零碎&#xff0c;自学起来难度非常大&#xff0c;不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》。本文是Android音视频任务列表的其中一个&#xff0c; 对应的要学习的内容是&#xff1a;如何使…

移动硬盘不显示盘符简单处理方法

通常情况下&#xff0c;将移动硬盘连接到电脑后会被赋予一个特定的盘符&#xff0c;以便用户可以访问和操作其中的文件和文件夹。然而&#xff0c;如果移动硬盘不显示盘符&#xff0c;意味着操作系统无法根据该硬盘的文件系统和存储信息识别出其所对应的盘符&#xff0c;这将导…

[LeetCode - Python]167.两数之和 II (Medium);125. 验证回文串(Easy)

1.题目&#xff1a; 167.两数之和 II &#xff08;Medium&#xff09; 1.代码&#xff1a; class Solution:def twoSum(self, numbers: List[int], target: int) -> List[int]:#由于数组是已按非递减顺序排列&#xff0c;因此可以对撞双指针&#xff1b;le , ri 0 , len…

JWT的使用

文章目录 前言一、在yml文件中配置参数二、创建JwtUtil.java三、创建JwtProperties.java四、创建JwtClaimsConstant.java五、创建JwtTokenAdminInterceptor.java六、注册到WebMvcConfiguration1.4.3 ThreadLocal 前言 一、在yml文件中配置参数 sky:jwt:# 设置jwt签名加密时使…

骨传导耳机是怎么工作的?骨传导耳机是智商税产品吗?

骨传导耳机是怎么工作的&#xff1f;骨传导耳机是智商税产品吗&#xff1f; 骨传导耳机是怎么工作的&#xff1f; 骨传导耳机的传声方式跟传统耳机完全不同&#xff0c;骨传导耳机就是利用骨传导的原理是直接将人体骨结构作为传声介质&#xff0c;通过颅骨来进行声音传播的&am…

物联网与5G引领智慧城市时代的到来

智慧城市需要依赖于多种技术&#xff0c;这些技术的应用将城市转变为高效、智能、可持续发展的现代化城市。智慧城市是基于信息技术、物联网和大数据等先进技术的融合&#xff0c;旨在提升城市的运行效率、资源利用效率和居民生活质量。以下是智慧城市需要依赖的主要技术&#…

GD32F103VE深度睡眠与唤醒

GD32F103VE深度睡眠与唤醒&#xff0c;执行WFI指令或执行1次WFE指令&#xff0c;命令CPU进入深度睡眠模式。 电源管理单元有3种省电模式:睡眠模式&#xff0c;深度睡眠模式和待机模式&#xff1b; 进入深度睡眠的步骤如下&#xff1a; 1,配置SLEEPDEEP1 2,配置STBMOD0 3,执行W…

[K8S:命令执行:权限异常:解决篇]:通过更新kubeconfig配置相关信息

文章目录 一&#xff1a;场景复现&#xff1a;1.1&#xff1a;关键信息&#xff1a;1.2&#xff1a;全异常日志输出&#xff1a; 二&#xff1a;解决流程&#xff1a;2.1&#xff1a;更新 kubeconfig&#xff1a;2.1.1&#xff1a;执行命令&#xff1a; 2.2&#xff1a;再次执行…

Android平台一对一音视频通话方案对比:WebRTC VS RTMP VS RTSP

一对一音视频通话使用场景 一对一音视频通话都需要稳定、清晰和流畅&#xff0c;以确保良好的用户体验&#xff0c;常用的使用场景如下&#xff1a; 社交应用&#xff1a;社交应用是一种常见的使用场景&#xff0c;用户可以通过音视频通话进行面对面的交流&#xff1b;在线教…

Android google admob Timeout for show call succeed 问题解决

项目场景&#xff1a; 项目中需要接入 google admob sdk 实现广告商业化 问题描述 在接入Institial ad 时&#xff0c;onAdLoaded 成功回调&#xff0c;但是onAdFailedToShowFullScreenContent 也回调了错误信息 “Timeout for show call succeed.” InterstitialAd.load(act…

算法刷题之路

刷题历程 - - - 基本数据结构 - - -数组、字符串、堆、栈、队列、链表739.每日温度&#xff08;栈&#xff09;155. 最小栈20. 有效的括号581.最短无序连续数组169. 多数元素&#xff08;数组&#xff09;136.只出现一次的数字128.最长连续序列560.和为k的子数组&#xff08;组…

yolo使用说明

yolo-v5代码 一、环境准备 yolo-v5更像是一个工程 算法和v4差不多&#xff0c;只是细节有所不同 拉取代码 环境要求 因为v6用到了torch1.6中的混合精度 二、数据准备 训练使用的是coco数据集 coco数据集很大&#xff0c;训练起来费时间&#xff0c;可以直接用自己数据集来做…

三、axios+vue

Axios 导入&#xff1a; <script src"https://unpkg.com/axios/dist/axios.min.js"></script> 基础语法&#xff1a; axios.get(?keyvalue&key2value2).then(function(response){},function(err){} axios.post(地址&#xff0c;{key:value,key2…

IDEA常用插件介绍

1.CodeGlance&#xff08;CodeGlance Pro&#xff09; 安装后&#xff0c;重新启动编译器即可。 CodeGlance是一款非常好用的代码地图插件&#xff0c;可以在代码编辑区的右侧生成一个竖向可拖动的代码缩略区&#xff0c;可以快速定位代码的同时&#xff0c;并且提供放大镜功能…

DARPA TC-engagement5数据集解析为json格式输出到本地

关于这个数据集的一些基本信息就不赘述了&#xff0c;参考我之前的博客。DARPA TC-engagement5数据集官方工具可视化 官方给的工具是将解析的数据存到elasticsearch的&#xff0c;但是数据集的解压增长率非常恐怖&#xff0c;对空间要求很高。因此针对这个问题&#xff0c;我对…

win10配置rocketmq

下载地址&#xff1a;下载 | RocketMQ ,版本根据自己情况定&#xff0c;我选用的是4.7.* 1、下载后解压。D:\rocketmq-all-4.7.0-bin-release 2、需要注意一下jdk安装目录的目录名不能有空格&#xff0c;否则会报错找不到JAVA 3、环境变量新增ROCKEMQ_THOMED:\rocketmq-all-4…

MySQL语句判断数据库数据重复情况,新增、删除、不变。

判断 7月8月两个月数据对比情况&#xff0c;新增、删除(离职)、重复。 根据manager_name,gg_name,employer,department,historical_office判断出是否重复数据 -- ●- 新增或离职 -- ●- 创建临时表CREATE TABLE temp_table (SELECT id,manager_name,gg_name,employer,departme…