C++STL与泛型编程(3)容器之分类与测试

文章目录

  • 容器的分类
  • 序列式容器(sequence containers)代码示例
    • 辅助函数
    • array 容器
      • array容器的测试代码
      • 测试代码中部分函数解析
    • vector 容器
      • vector 容器的测试代码
      • 测试代码中部分函数解析
    • list 容器
      • list 容器的测试代码
      • 测试代码中部分函数解析
    • forward_list 容器
    • deque 容器
      • stack 容器
      • queue 容器
  • 关联式容器(Associative Containers)代码示例
    • multiset 容器
      • multiset 容器测试代码
    • multimap 容器
      • multimap 容器测试代码
    • unordered_multiset 容器
      • unordered_multiset 容器测试代码
    • unordered_multimap 容器
    • set容器,map容器
    • unordered_set 容器
    • unordered_map 容器

容器的分类

  • 序列式容器(sequence containers)

    • Array
      • 连续空间,大小不能扩充
    • Vector
      • 连续空间,前面不可以扩充,后面可以扩充,
    • Deque
      • 连续空间,前后都可以扩充,
    • List
      • 双向链表,每一个元素带有两个指针,其占用内存比单向链表要多
    • Forward-List
      • 单向链表

    在这里插入图片描述

  • 关联式容器(Associative Containers)(有key和value,适合做快速查找操作)

    • set/Multiset
      • set的key就是value,value就是key,set元素不能重复,Multiset元素可以重复
    • Map/Multimap
      • Map的每一个结点都有一个key和value,Map元素的key不能重复,Multimap元素的key可以重复
        在这里插入图片描述
  • 不定序容器(Unordered Containers)(是关联式容器中的一种,底部结构是hashtable)
    在这里插入图片描述

序列式容器(sequence containers)代码示例

辅助函数

//得到目标long
long get_a_target_long() {long target = 0;cout << "target (0~" << RAND_MAX << "):";cin >> target;return target;
}
//得到目标string
string get_a_target_string() {long target = 0;char buf[10];cout << "target (0~" << RAND_MAX << "):";cin >> target;//snprintf 将数值target转换成字符串snprintf(buf,10,"%d",target);return string(buf);
}
//比较两个long是否相等
int compareLongs(const void *a, const void *b) {return (*(long*)a- *(long*)b);
}
//比较两个string是否相等
int compareStrings(const void *a, const void *b) {if (*(string*)a > *(string*)b)return 1;else if (*(string*)a < *(string*)b)return -1;elsereturn 0;
}

array 容器

array<long,ASIZE> c;	array数组,第一个参数是容器中的类型,第二个参数是数组的大小。
array.size();	array的大小
array.front();	array的第一个元素
array.back();	array的最后一个元素
array.data();	array数组的首地址

array容器的测试代码

#include<iostream>
#include<array>
#include<ctime>
#include<cstdlib>//using namespace std;const int ASIZE = 50000;void test_array() {cout << "test_array() starting......" << endl;array<long, ASIZE> c ;clock_t timeStart = clock();for (long i = 0; i < ASIZE;++i) {c[i] = rand();}cout << "array数组中插入50000个元素所用时间:" << clock()- timeStart <<endl;cout << "array大小是:" << c.size() << endl;cout << "array中第一个元素是:" << c.front() << endl;cout << "array中最后一个元素是:" << c.back() << endl;cout << "array首地址是:" << c.data() << endl;//设定目标long值long target = get_a_target_long();timeStart = clock();qsort(c.data(),ASIZE,sizeof(long),compareLongs);long* pItem=(long*)bsearch(&target,c.data(), ASIZE, sizeof(long), compareLongs);cout << "qsort和bsearch所用时间:" << clock() - timeStart << endl;if (pItem != NULL)cout << *pItem << "在数组中,已找到!" << endl;elsecout << *pItem << "不在数组中!" << endl;
}
//调用test_array()
int main() {test_array();system("pause");return 0;
}

输出结果:

test_array() starting......
array数组中插入50000个元素所用时间:8
array大小是:50000
array中第一个元素是:41
array中最后一个元素是:14499
array首地址是:001CF028
target (0~32767):2000
qsort和bsearch所用时间:43
2000在数组中,已找到!

测试代码中部分函数解析

qsort和bsearch在cstdlib文件中
qsort(容器首地址,容器中元素数量,每一个元素的字节大小,排序方式)
bsearch(查询内容的地址,容器首地址,容器中元素数量,每一个元素的字节大小,排序方式)

vector 容器

vector容器的空间大小是两倍两倍的增长。其中两倍增长的意思是,当空间大小不够时,在另一块空间找到两倍大小的空间,将数据进行搬移到另一空间,而不是在原有空间的基础上进行增长。主要原因是因为vector空间连续。

vector<string> c;声明一个vector,第一参数是元素类型,第二参数是分配器,不写的话即是默认分配器vector.size() 是真正元素的个数
vector.capacity()是当前空间的大小
vector.push_back()是往vector里放数据以下功能同array:
vector.front()
vector.back()
vector.data()

vector 容器的测试代码

#include<vector>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<string>using namespace std;void test_vector(long& targets) {cout << "test_vector() starting......" << endl;vector<string> c;char buf[10];clock_t timeStart = clock();for (long i = 0; i < targets; ++i) {snprintf(buf, 10, "%d", rand());c.push_back(string(buf));}cout << "vector中插入50000个元素所用时间:" << clock() - timeStart << endl;cout << "vector大小是:" << c.size() << endl;cout << "vector容量是:" << c.capacity() << endl;cout << "vector中第一个元素是:" << c.front() << endl;cout << "vector中最后一个元素是:" << c.back() << endl;cout << "vector首地址是:" << c.data() << endl;//设定目标值string target = get_a_target_string();timeStart = clock();auto ite=find(c.begin(),c.end(),target);cout << "find所用时间:" << clock() - timeStart << endl;if (ite != c.end())cout << *ite << "在vector中,已找到!" << endl;elsecout << *ite << "不在vector中!" << endl;timeStart = clock();sort(c.begin(), c.end());string* pItem = 	(string*)bsearch(&target,c.data(),c.size(),sizeof(string),compareStrings);cout << "sort+bsearch所用时间:" << clock()-timeStart<<endl;if (pItem != NULL)cout << *pItem << "在vector中,已找到!" << endl;elsecout << *pItem << "不在vector中!" << endl;
}
//调用test_vector函数
int main() {long targets = 50000;test_vector(targets);system("pause");return 0;
}

输出结果:

test_vector() starting......
vector中插入50000个元素所用时间:2047
vector大小是:50000
vector容量是:61447
vector中第一个元素是:41
vector中最后一个元素是:14499
vector首地址是:00970060
target (0~32767):1357
find所用时间:18
1357在vector中,已找到!
sort+bsearch所用时间:4094
1357在vector中,已找到!

测试代码中部分函数解析

首尾迭代器是前闭后开区间的形式

find(首迭代器,尾迭代器,搜寻的目标值)
sort(首迭代器,尾迭代器)
sort(首迭代器,尾迭代器,Compare comp) 其中,comp接受两个参数,返回bool值,comp是给出比较两个数的大小关系的方式

list 容器

list是每增加一个元素就增加一个对应大小的空间,其存储空间是不连续的。空间利用率高,但搜索数据慢。

 list<string>c;	声明一个list,第一参数是元素类型,第二参数是分配器list.size() 是真正元素的个数list.capacity()是当前空间的大小list.push_back()是往vector里放数据以下功能同array:list.front()list.back()list.data()

list 容器的测试代码

#include<list>
#include<algorithm>
#include<functional>
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<string>
using namespace std;void test_list(long& targets) {cout << "test_list() starting......" << endl;list<string> c;char buf[10];clock_t timeStart = clock();for (long i = 0; i < targets; ++i) {snprintf(buf, 10, "%d", rand());c.push_back(string(buf));}cout << "list中插入50000个元素所用时间:" << clock() - timeStart << endl;cout << "list大小是:" << c.size() << endl;cout << "list max_size大小是:" << c.max_size() << endl;cout << "list中第一个元素是:" << c.front() << endl;cout << "list中最后一个元素是:" << c.back() << endl;//设定目标值string target = get_a_target_string();timeStart = clock();auto ite = find(c.begin(), c.end(), target);cout << "find所用时间:" << clock() - timeStart << endl;if (ite != c.end())cout << *ite << "在list中,已找到!" << endl;elsecout << *ite << "不在list中!" << endl;timeStart = clock();c.sort();cout << "sort所用时间:" << clock() - timeStart << endl;}
//调用test_list函数
int main() {long targets = 50000;test_list(targets);system("pause");return 0;
}

输出结果

test_list() starting......
list中插入50000个元素所用时间:840
list大小是:50000
list max_size大小是:119304647
list中第一个元素是:41
list中最后一个元素是:14499
target (0~32767):1234
find所用时间:12
1234在list中,已找到!

测试代码中部分函数解析

list和 forward_list都有自己的sort函数
c.sort();是容器中的sort函数,不是标准库中的sort函数,当容器中有sort函数时,优先选择容器中的sort函数

forward_list 容器

forward_list<string>c;	声明一个forward_list
forward_list.push_front()	只有push_front()没有push_back(),即从beginning开始插入数据,比较快,从后面插入数据太慢,
forward_list.front()	首元素,没有forward_list.back(),没有forward_list.size()找forward_list里的元素,可用auto pItem=::find(c.begin(),c.end(),target),
::表示全局,即标准库中的find函数,返回的pItem是一个迭代器

deque 容器

双向开口,可进可出的连续性存储空间,但它是分段连续,
即在每一段中是连续的,段与段之间不连续,但在使用过程中,我们会觉得deque是整个连续的
当deque的空间不够用时,调用push_back时,会再分配一段空间使用deque<string>c; deque的声明
size(),front(),back(),max_size()函数意义同上找deque里的元素,可用auto pItem=::find(c.begin(),c.end(),target),deque自身没有sort函数,排序要用全局的sort,即  ::sort(c.begin(),c.end());

在这里插入图片描述
stack和queue容器没有新的技术,是使用deque得到的,一般不称为容器,而是称为容器适配器(container adapters)。stack和queue不提供迭代器相关操作,因为如果有迭代器相关操作的话,则stack和queue就可以改变其内部的数据,不再符合先进后出和先进先出的特性。

stack 容器

先进后出stack<string>c; stack的声明
size()
top()	返回最顶部数据,不弹出
pop()	最顶部元素弹出来
push()	元素放进去

queue 容器

先进先出queue<string>c; queue的声明
size()
front()
back()
pop()	元素弹出来
push()	元素放进去

关联式容器(Associative Containers)代码示例

multiset 容器

没有push_back,没有push_front
multiset<string>c;
multiset.insert()	插入元素
multiset.size()
multiset.max_size()搜寻某数据,multiset.find()比::find()快

multiset 容器测试代码

#include<set>
#include<algorithm>
#include<functional>
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<string>using namespace std;void test_multiset(long& targets) {cout << "test_multiset() starting......" << endl;multiset<string> c;char buf[10];clock_t timeStart = clock();for (long i = 0; i < targets; ++i) {snprintf(buf, 10, "%d", rand());c.insert(string(buf));}cout << "multiset中插入50000个元素所用时间:" << clock() - timeStart << endl;cout << "multiset大小是:" << c.size() << endl;cout << "multiset max_size大小是:" << c.max_size() << endl;//设定目标值string target = get_a_target_string();timeStart = clock();auto ite = find(c.begin(), c.end(), target);cout << "find所用时间:" << clock() - timeStart << endl;if (ite != c.end())cout << *ite << "在multiset中,已找到!" << endl;elsecout << *ite << "不在multiset中!" << endl;timeStart = clock();c.find(target);cout << "multiset容器中find所用时间:" << clock() - timeStart << endl;}
//调用test_multiset函数int main() {long targets = 50000;test_multiset(targets);system("pause");return 0;
}

输出结果,可以看出,容器自带的find函数快

test_multiset() starting......
multiset中插入50000个元素所用时间:2966
multiset大小是:50000
multiset max_size大小是:97612893
target (0~32767):88
find所用时间:62
88在multiset中,已找到!
multiset容器中sort所用时间:0

multimap 容器

multimap<long,string>c;	声明multimap
multimap.insert(pair<long,string>(i,buf));	插入key,value
multimap不可用[]做插入操作

multimap 容器测试代码

#include<map>
#include<algorithm>
#include<functional>
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<string>using namespace std;void test_multimap(long& targets) {cout << "test_multimap() starting......" << endl;multimap<long,string> c;char buf[10];clock_t timeStart = clock();for (long i = 0; i < targets; ++i) {snprintf(buf, 10, "%d", rand());c.insert(pair<long, string>(i,string(buf)));}cout << "multimap中插入50000个元素所用时间:" << clock() - timeStart << endl;cout << "multimap大小是:" << c.size() << endl;cout << "multimap max_size大小是:" << c.max_size() << endl;//设定目标long值long target = get_a_target_long();timeStart = clock();auto pItem=c.find(target);cout << "multimap容器中find所用时间:" << clock() - timeStart << endl;if (pItem != c.end())cout << "key为:" << pItem->first << " 在multimap中已找到,其value为:" << pItem->second << endl;elsecout << "key为:" << pItem->first << " 在multimap中不存在" << endl;}//调用test_multimap函数
int main() {long targets = 50000;test_multimap(targets);system("pause");return 0;
}

输出结果

test_multimap() starting......
multimap中插入50000个元素所用时间:2760
multimap大小是:50000
multimap max_size大小是:89478485
target (0~32767):30000
multimap容器中find所用时间:0
key为:30000 在multimap中已找到,其value为:8970

unordered_multiset 容器

unordered_multiset 容器底层结构是hashtable,multiset和multimap底层结构是红黑树

#include<unordered_set>
unordered_multiset<string> c;c.size()
c.max_size()
c.bucket_count();	bucket的个数
c.load_factor();	载重因子
c.max_load_factor();	最大载重因子为1
c.max_bucket_count();	最大bucket个数
c.bucket_size(i);

unordered_multiset 容器测试代码

#include<unordered_set>
#include<algorithm>
#include<functional>
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<string>using namespace std;void test_unordered_multiset(long& targets) {cout << "test_unordered_multiset() starting......" << endl;unordered_multiset<string> c;char buf[10];clock_t timeStart = clock();for (long i = 0; i < targets; ++i) {snprintf(buf, 10, "%d", rand());c.insert(string(buf));}cout << "unordered_multiset中插入50000个元素所用时间:" << clock() - timeStart << endl;cout << "unordered_multiset size是:" << c.size() << endl;cout << "unordered_multiset max_size大小是:" << c.max_size() << endl;cout << "unordered_multiset bucket_count()是:" << c.bucket_count() << endl;cout << "unordered_multiset load_factor()是:" << c.load_factor() << endl;cout << "unordered_multiset max_load_factor()是:" << c.max_load_factor() << endl;cout << "unordered_multiset max_bucket_count()是:" << c.max_bucket_count() << endl;for (int i = 0; i < 20;++i) {cout << "bucket # " << i << " has " << c.bucket_size(i) << " elements" << endl;}//设定目标值string target = get_a_target_string();timeStart = clock();auto ite = find(c.begin(), c.end(), target);cout << "find所用时间:" << clock() - timeStart << endl;if (ite != c.end())cout << *ite << "在unordered_multiset中,已找到!" << endl;elsecout << *ite << "不在unordered_multiset中!" << endl;timeStart = clock();c.find(target);cout << "unordered_multiset容器中find所用时间:" << clock() - timeStart << endl;}

输出结果

test_unordered_multiset() starting......
unordered_multiset中插入50000个元素所用时间:3668
unordered_multiset size是:50000
unordered_multiset max_size大小是:119304647
unordered_multiset bucket_count()是:65536
unordered_multiset load_factor()是:0.762939
unordered_multiset max_load_factor()是:1
unordered_multiset max_bucket_count()是:536870911
bucket # 0 has 0 elements
bucket # 1 has 0 elements
bucket # 2 has 2 elements
bucket # 3 has 0 elements
bucket # 4 has 8 elements
bucket # 5 has 2 elements
bucket # 6 has 0 elements
bucket # 7 has 0 elements
bucket # 8 has 0 elements
bucket # 9 has 0 elements
bucket # 10 has 0 elements
bucket # 11 has 0 elements
bucket # 12 has 0 elements
bucket # 13 has 0 elements
bucket # 14 has 0 elements
bucket # 15 has 0 elements
bucket # 16 has 0 elements
bucket # 17 has 0 elements
bucket # 18 has 0 elements
bucket # 19 has 0 elements
target (0~32767):1357
find所用时间:36
1357在unordered_multiset中,已找到!
unordered_multiset容器中find所用时间:0

unordered_multimap 容器

使用方法同multimap

set容器,map容器

使用方法同multiset,multimap,但是插入数据不重复
map可以用[]插入数据,例 map[key]=value;

unordered_set 容器

unordered_map 容器

底层结构是hashtable,用法同set和map

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

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

相关文章

C++面试题目

C和C的区别 总览 C是一个结构化语言&#xff0c;它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程&#xff0c;对输入&#xff08;或环境条件&#xff09;进行运算处理得到输出&#xff08;或实现过程&#xff08;事务&#xff09;控制&#xff09;。C&…

C++STL与泛型编程(4)OOP(面向对象编程) Vs. GP(泛型编程)

文章目录OOP和GP为什么list不能使用标准库中的::sort算法&#xff1f;采用GP的好处OOP和GP OOP将datas和methods关联在一起 GP将datas和methods分开 为什么list不能使用标准库中的::sort算法&#xff1f; 因为标准库的sort的算法用到了随机访问迭代器&#xff08;RandomAcce…

牛客网 链表结构 算法相关内容

链表结构 单链表的节点结构 由以下结构的节点依次连接起来所形成的链叫单链表结构 Clas Node<V>{ V value; Node next; } 双链表的节点结构 由以下结构的节点依次连接起来所形成的链叫双链表结构 Clas Node<V>{ V value; Node next; Node last; } 单链表和双…

C++ primer 第8章 IO库

文章目录IO库类型和头文件IO对象无拷贝或赋值IO流的条件状态文件输入输出ifstream 示例ofstream 示例文件模式以out模式打开文件会丢弃已有数据每次调用open时都会确定文件模式ofstream 保留源文件 追加数据 示例string流istringstream示例ostringstream示例IO库类型和头文件 …

C++面试宝典 基本语言(三)

如果同时定义了两个函数&#xff0c;一个带const&#xff0c;一个不带&#xff0c;会有问题吗&#xff1f; 不会&#xff0c;这相当于函数的重载 #include<iostream> class A{ public:void print()const{std::cout << "Hello" << std::endl;}void…

C++ primer 第9章 顺序容器

文章目录顺序容器类型确定使用哪种顺序容器容器库概览容器操作迭代器迭代器支持的所有操作迭代器支持的所有运算迭代器范围对构成范围的迭代器的要求标准库迭代器范围左闭右开的三种性质容器定义和初始化将一个新容器创建为另一个容器的拷贝将array拷贝到vector中的代码与顺序容…

牛客网C++面经 容器和算法

原文网址 参考网址 C语言中文网 请你来说一下map和set有什么区别&#xff0c;分别又是怎么实现的&#xff1f; map和set都是C的关联容器&#xff0c;其底层实现都是红黑树&#xff08;RB-Tree&#xff09;。由于 map 和set所开放的各种操作接口&#xff0c;RB-tree 也都提供…

C++ primer 第10章 泛型算法

文章目录概述findcount初识泛型算法只读算法只读算法accumulate只读算法equal写容器元素的算法算法fill算法fill_nback_inserter算法copy算法replace replace_copy重排容器元素的算法sortuniqueunique_copy定制操作向算法传递函数谓词算法stable_sort算法partitionlambda表达式…

C语言常用字符串函数

概括 代码 #include<stdlib.h> #include<stdio.h> #include<string.h> int main() {//常用字符串函数char a[]"abcSDFbnm";char b[]"SD";printf("a的字符串长度:%d\n",strlen(a));printf("b的字符串长度:%d\n",str…

C++ primer 第11章 关联容器

文章目录使用关联容器map示例关联容器概述定义关联容器关联容器值初始化multimap和multiset关键字类型的要求pair类型pair上的操作关联容器操作关联容器额外的类型别名关联容器迭代器map迭代器set迭代器关联容器和算法添加元素向map添加元素检测insert的返回值使用insert代替下…

C++ primer 第12章 动态内存

文章目录前言动态内存与智能指针shared_ptr类shared_ptr和unique_ptr都支持的操作shared_ptr独有的操作make_shared 函数shared_ptr的拷贝和赋值shared_ptr自动销毁所管理的对象shared_ptr还会自动释放相关联的内存程序使用动态内存出于以下原因直接管理内存使用new动态分配和初…

C语言顺序查找二分查找

介绍 顺序查找 按照顺序一个个查找 #include<stdio.h> //顺序查找 int search(int arr[],int len,int aim) {int i;for(i0;i<len;i){if(arr[i]aim){return i;//返回下标 }}return -1;//表示未查询到} int main() {int arr[]{13,355,256,65,234,-1,35,-6,-3,-4,0};…

C++ primer 第12章 12.3 使用标准库:文本查询程序

文章目录使用标准库&#xff1a;文本查询程序文本查询程序设计数据结构在类之间共享数据自己的文本查询程序书中的文本查询程序使用标准库&#xff1a;文本查询程序 我们将实现一个简单的文本查询程序&#xff0c;作为标准库相关内容学习的总结。 我们的程序允许用户在一个给…

C语言二维数组 int arr[2][3]

基础使用 先遍历行再遍历列 #include<stdio.h> //二维数组的基本使用 int main() {//二维数组的初始化int arr1[2][2]{{2,2},{0,0}};int arr2[2][3]{2,2,2,8,8,8};int arr3[6][9];int i,j;for(i0;i<6;i){for(j0;j<9;j){arr3[i][j]1;}}arr3[2][5]0;//打印printf(&…

C++ primer 第13章 拷贝控制

文章目录前言拷贝、赋值与销毁拷贝构造函数合成拷贝构造函数拷贝初始化和直接初始化拷贝初始化的发生&#xff1a;参数和返回值拷贝初始化的限制拷贝赋值运算符重载赋值运算符合成拷贝赋值运算符析构函数析构函数完成的工作什么时候会调用析构函数合成析构函数代码片段调用几次…

C语言 指针自增自减加减运算 p++ p+i

介绍 自增自减代码 #include<stdio.h> #include<string.h> //指针自增--short void increase(short *arr,int len) {int i;arr&arr[0];for(i0;i<len;i){printf("arr[%d]%d,address%p\n",i,*arr,arr);arr;} }//指针自减--char void decrease(char…

C++ 编译与底层

原文链接 编译与底层请你来说一下一个C源文件从文本到可执行文件经历的过程&#xff1f; 对于C源文件&#xff0c;从文本到可执行文件一般需要四个过程&#xff1a;预处理阶段&#xff1a;对源代码文件中文件包含关系&#xff08;头文件&#xff09;、预编译语句&#xff08;…

C语言 指针数组-字符指针数组整型指针数组 char*s[3] int*a[5] 数组指针int(*p)[4]

基本介绍 1.指针数组:由n个指向整型元素的指针而组成,里面存放指针 Int *ptr[3]; 2.地址: ptr[i]:元素地址 &ptr[i]:指针地址 图示 代码: 内存布局: 代码 #include<stdio.h> #include<string.h> //指针数组--int void pointer(int *arr,int len) {int …

C语言 多重指针--整型字符字符串 int**pp

介绍 多重指针:一个指针指向另一个指针 离值越近的指针级别越大:一级 内存布局 代码 图示: 多重指针–整型 #include<stdio.h> #include<string.h> //多重指针--整型//二级指针 void two() {printf("二级指针:\n");int a896;int *p&a,**pp&…

C++ primer 第13章 拷贝控制

文章目录前言拷贝、赋值与销毁拷贝构造函数合成拷贝构造函数拷贝初始化和直接初始化拷贝初始化的发生&#xff1a;参数和返回值拷贝初始化的限制拷贝赋值运算符重载赋值运算符合成拷贝赋值运算符析构函数析构函数完成的工作什么时候会调用析构函数合成析构函数代码片段调用几次…