哈希密钥:解锁unordered容器的极速潜能

目录

一.unordered系列关联式容器

二:unordered_set

1:unordered_set用法详解

1.1:模板参数介绍

1.2:unordered_set的构造函数

1.3:常用接口使用

1.3.1:insert与erase

1.3.2:find与size与empty

1.3.3:clear与swap与count

1.3.4:迭代器

1.3.5:桶操作

三:unordered_map

1:unorder_map用法详解

1.1:模板参数介绍

1.2:unordered_map的接口说明

1.2.1:unordered_map的构造函数

1.2.2:unordered_map的容量

1.2.3:unordered_map的迭代器

1.2.4:unordered_map的元素访问

1.2.5:unordered_map的查询

1.2.6:unordered_map的修改操作

1.2.6.1:insert与erase

1.2.6.2:clear与swap

1.2.7:unordered_map的桶操作

四:unordered_set和set的使用差异

五:unordered_map和map的使用差异


一.unordered系列关联式容器

在C++98中,STL提供了底层为红黑树结构的一系列关联式容器在查询时效率可达到log2N,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好
的查询是,进行很少的比较次数就能够将元素找到,因此在C++11中,STL又提供了4个
unordered系列的关联式容器,这四个容器与红黑树结构的关联式容器使用方式基本类似,只是
其底层结构不同.

二:unordered_set

  1. unordered_set是不按特定顺序存储键值的关联式容器,其允许通过键值快速的索引到对应的元素。
  2. 在unordered_set中,元素的值同时也是唯一地标识它的key。
  3. 在内部,unordered_set中的元素没有按照任何特定的顺序排序,为了能在常数范围内找到指定的Key,unordered_set将相同哈希值的键值放在相同的桶中。
  4. 在unordered_set容器通过key访问单个元素要比set快,但它通常在遍历元素子集的范围迭代效率较低。
  5. 它的迭代器至少是前向迭代器。

1:unordered_set用法详解

1.1:模板参数介绍

cpp 复制代码
template < class Key,                        // unordered_set::key_type/value_type
           class Hash = hash<Key>,           // unordered_set::hasher
           class Pred = equal_to<Key>,       // unordered_set::key_equal
           class Alloc = allocator<Key>      // unordered_set::allocator_type
           > class unordered_set;

1 .Key(键类型)

  • 用于定义键的数据类型,必须是可哈希可比较的

2.Hash(哈希函数类型,默认:std::hash<Key>)

  • 将键转换为size_t类型的哈希值,可以使用stl内置的哈希函数,该参数可以缺省,如果用unordered_SET存储自定义数据类型,则需要自己设置哈希函数.

3.KeyEqual(键相等比较函数,默认:std::equal_to<Key>)

  • **判断两个键是否相等,**可以使用stl内置的键相等比较函数,该参数可缺省,如果用unordered_set存储自定义数据类型,则需要自己设计键相等比较函数,该函数是实现键值去重和查找必不可少的.

4.Allocator(分配器类型,默认:std::allocator<pair<const Key, T>>)

  • 管理内存的分配和释放

1.2:unordered_set的构造函数

  1. 构造一个某类型的空容器。
  2. 拷贝构造某同类型容器的复制品。
  3. 使用迭代器拷贝构造某一段内容。
cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>

int main()
{
	vector<int> v1 = { 1,2,3,4,5,6,7,8,9 };
	//构造
	unordered_set<int> s1;
	//拷贝构造
	unordered_set<int> s2(s1);
	//迭代器构造
	unordered_set<int> s3(v1.begin(), v1.end());
	
	for (const auto& e : s3)
		cout << e << " ";
	cout << endl;
	return 0;
}

1.3:常用接口使用

|----------|-----------------|
| 成员函数 | 功能 |
| insert | 插入指定元素 |
| erase | 删除指定元素 |
| find | 查找指定元素 |
| size | 获取容器中元素的个数 |
| empty | 判断容器是否为空 |
| clear | 清空容器 |
| swap | 交换两个容器中的数据 |
| count | 获取容器中指定元素值的元素个数 |

1.3.1:insert与erase
cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>


void TestInsertAndErase()
{
	unordered_set<int> us1;
	us1.insert(1);
	us1.insert(2);
	us1.insert(7);
	us1.insert(5);
	us1.insert(9);
	us1.insert(25);
	us1.insert(4);
	for (const auto& e : us1)
		cout << e << " ";
	cout << endl;
	us1.erase(25);
	us1.erase(9);
	us1.erase(7);
	for (const auto& e : us1)
		cout << e << " ";
	cout << endl;
}

int main()
{
	TestInsertAndErase();
}
1.3.2:find与size与empty
cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>

void TestFindAndSizeAndEmpty()
{
	unordered_set<int> us1;
	us1.insert(1);
	us1.insert(2);
	us1.insert(7);
	us1.insert(5);
	us1.insert(9);
	us1.insert(25);
	us1.insert(4);
	//返回的是该数值的迭代器
	cout << *(us1.find(5)) << endl;
	cout << "Size:>" << us1.size() << endl;
	cout << us1.empty() << endl;
}

int main()
{
	TestFindAndSizeAndEmpty();
}
1.3.3:clear与swap与count
cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>

void TestInsertAndErase()
{
	unordered_set<int> us1;
	us1.insert(1);
	us1.insert(2);
	us1.insert(7);
	us1.insert(5);
	us1.insert(9);
	us1.insert(25);
	us1.insert(4);
	for (const auto& e : us1)
		cout << e << " ";
	cout << endl;
	us1.erase(25);
	us1.erase(9);
	us1.erase(7);
	for (const auto& e : us1)
		cout << e << " ";
	cout << endl;
}
void TestFindAndSizeAndEmpty()
{
	unordered_set<int> us1;
	us1.insert(1);
	us1.insert(2);
	us1.insert(7);
	us1.insert(5);
	us1.insert(9);
	us1.insert(25);
	us1.insert(4);
	//返回的是该数值的迭代器
	cout << *(us1.find(5)) << endl;
	cout << "Size:>" << us1.size() << endl;
	cout << us1.empty() << endl;
}

void TestClearAndSwapAndCount()
{
	unordered_set<int> us1;
	us1.insert(1);
	us1.insert(2);
	us1.insert(7);
	us1.insert(5);
	us1.insert(9);
	us1.insert(25);
	us1.insert(4);
	unordered_set<int> us2;
	us2.insert(6);
	us2.insert(3);
	us2.insert(8);
	us2.insert(11);
	us2.insert(17);
	us2.insert(20);
	us2.insert(20);
	us2.insert(20);
	cout << "交换前" << endl;
	for (auto& e : us1)
		cout << e << " ";
	cout << endl;
	for (auto& e : us2)
		cout << e << " ";
	cout << endl;
	us1.swap(us2);
	cout << "交换后" << endl;
	for (auto& e : us1)
		cout << e << " ";
	cout << endl;
	for (auto& e : us2)
		cout << e << " ";
	cout << endl;

	cout <<"us1.count(2):>" << us1.count(2) << endl;
	cout <<"us2.count(20):>" << us1.count(20) << endl;
	us1.clear();
	us2.clear();
	cout << "us1:size:>" << us1.size() << endl;
	cout << "us2:size:>" << us2.size() << endl;
}

int main()
{
	TestClearAndSwapAndCount();
}
1.3.4:迭代器
cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>


void TestIterator()
{
	unordered_set<int> us1 = { 10,20,30,40,50,60 };
	unordered_set<int>::iterator it = us1.begin();
	while(it != us1.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	for (auto& element : us1)
		cout << element << " ";
	cout << endl;
}

int main()
{
	TestIterator();
}
1.3.5:桶操作

STL实现哈希表示意图,对于哈希值相同的元素,STL选择将其用链表链接起来,挂到同一个桶上面去。

  • 在C++ STL中,unordered_setunordered_map默认最大负载因子是 1.0(负载因子 = 插入元素数量 / 桶数量)
  • 这意味着当容器中的元素数量超过桶的数量时(即负载因子 > 1.0),就会触发扩容。
cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>


void TestBucket()
{
	unordered_set<int> uset = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

	cout << "bucket_count: " << uset.bucket_count() << endl;  // 桶的数量
	cout << "max_bucket_count: " << uset.max_bucket_count() << endl;
	cout << "load_factor: " << uset.load_factor() << endl;  // 负载因子
	cout << "max_load_factor: " << uset.max_load_factor() << endl;  // 最大负载因子

	// 遍历桶
	for (size_t i = 0; i < uset.bucket_count(); ++i) 
	{
		cout << "Bucket " << i << " has " << uset.bucket_size(i) << " elements" << endl;
	}

	// 查找元素所在的桶
	int val = 5;
	cout << val << " is in bucket " << uset.bucket(val) << endl;
}

int main()
{
	TestBucket();
}

三:unordered_map

  1. unordered_map是存储<key,value>键值对的关联式容器,其允许通过keys快速的索引到与其对应的value.
  2. 在unordered_map中,键值通常用于唯一地标识元素,而映射值是一个对象,其内容与此键关联。键和映射值的类型可能不同。
  3. 在内部,unordered_map没有对<key,value>按照任何特定的顺序排序,为了能在常数范围内找到key所对应的value,unordered_map将相同哈希值的键值对放在相同的桶中。
  4. unordered_map容器通过key访问单个元素要比map快,但它通常在遍历元素子集的范围迭代方面效率较低。
  5. unordered_maps实现了直接访问操作符(operator[]),它允许使用key作为参数直接访问value
  6. 它的迭代器至少是前向迭代器.

1:unorder_map用法详解

1.1:模板参数介绍

cpp 复制代码
template < class Key,                                    // unordered_map::key_type
           class T,                                      // unordered_map::mapped_type
           class Hash = hash<Key>,                       // unordered_map::hasher
           class Pred = equal_to<Key>,                   // unordered_map::key_equal
           class Alloc = allocator< pair<const Key,T> >  // unordered_map::allocator_type
           > class unordered_map;
  • Key**(键类型)**
    • 定义键的数据类型,必须是可哈希和可比较的
  • T**(值类型)**
    • 定义与键关联的的值的类型.
  • Hash**(哈希函数类型,默认:std::hash<Key>)**
    • 将键转换为size_t类型的哈希值
  • KeyEqual(键相等比较函数,默认std::equal_to<Key>
    • 判断两个键是否相等,内置数据类型和string类,可以使用stl内置的键相等比较函数,该参数可缺省,如果用unordered_set存储自定义数据类型,则需要自己设计键相等比较函数,该函数是实现键值去重和查找必不可少的。
  • Allocator(分配器类型,默认:std::allocator<pair<const Key, T>>
    • 管理内存的分配和释放,绝大多数情况使用默认分配器,特殊场景(如嵌入式系统、实时系统)可能需要自定义分配器.

1.2:unordered_map的接口说明

1.2.1:unordered_map的构造函数
cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>
#include <unordered_map>


void TestConstructor()
{
	unordered_map<string, int> m1{ {"abc", 1}, {"awb", 2}, {"ccd", 3} };
	unordered_map<string, int> m2(m1);
	unordered_map<string, int> m3;
}

int main()
{
	TestConstructor();

	return 0;
}
1.2.2:unordered_map的容量

|-------------------------------|--------------------------------------|
| 函数声明 | 功能介绍 |
| bool empty() const | 检测 unordered_map 是否为空 |
| size_t size() const | 获取 unordered_map 的有效元素个数 |

cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>
#include <unordered_map>


void TestCapacity()
{
	unordered_map<string, int> m1{ {"abc", 1}, {"awb", 2}, {"ccd", 3} };
	cout << m1.size() << endl;
	cout << m1.empty() << endl;
}
int main()
{
	TestConstructor();
	TestCapacity();
	return 0;
}
1.2.3:unordered_map的迭代器

|----------|-------------------------------------------------------------|
| 函数声明 | 功能介绍 |
| begin | 返回 unordered_map 第一个元素的迭代器 |
| end | 返回 unordered_map 最后一个元素下一个位置的迭代器 |
| cbegin | 返回 unordered_map 第一个元素的 const 迭代器 |
| cend | 返回 unordered_map 最后一个元素下一个位置的 const 迭代器 |

cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>
#include <unordered_map>


void TestIterator()
{
	unordered_map<string,int> m1{ {"abc", 1}, {"awb", 2}, {"ccd", 3} };
	unordered_map<string, int>::iterator it = m1.begin();
	while (it != m1.end())
	{
		cout << it->first << " " << it->second << endl;
		++it;
	}
	cout << endl;
	unordered_map<string, int>::const_iterator rit = m1.cbegin();
	while (rit != m1.cend())
	{
		cout << rit->first << " " << rit->second << endl;
		++rit;
	}
}

int main()
{
	TestIterator();
	return 0;
}
1.2.4:unordered_map的元素访问

|--------------|------------------------|
| 函数声明 | 功能介绍 |
| operator[] | 返回与key对应的value,没有一个默认值 |

注意:该函数中实际调用哈希桶的插入操作,用参数key与V()构造一个默认值往底层哈希桶
中插入,如果key不在哈希桶中,插入成功,返回V(),插入失败,说明key已经在哈希桶中,将key对应的value返回.

cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>
#include <unordered_map>
void TestElementAccess()
{
	unordered_map<string, int> m1 = { {"abc",1},{"awb",2}};
	cout << m1["abc"] << endl;
	cout << m1["awb"] << endl;
	cout << m1["ccd"] << endl;
	cout << endl;
}

int main()
{
	TestElementAccess();
	return 0;
}
1.2.5:unordered_map的查询

|------------------------------|------------------------------------|
| 函数声明 | 功能介绍 |
| iterator find(const K& key) | 返回 key 在哈希桶中的位置 |
| size_t count(const K & key) | 返回哈希桶中关键码为 key 的键值对的个数 |

cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>
#include <unordered_map>


void TestFindAndCount()
{
	unordered_map<string, int> m1 = { {"abc",1},{"awb",2},{"ccd",3},{"awd",4} };
	unordered_map<string, int>::iterator it = m1.find("abc");
	cout << it->first << ":" << it->second << endl;
	cout << m1.count("abc") << endl;
}

int main()
{
	TestFindAndCount();
	return 0;
}


注意:unordered_map中key是不能重复的,因此count函数的返回值最大为1

1.2.6:unordered_map的修改操作

|----------------------------|-----------------|
| 函数声明 | 功能介绍 |
| insert | 向容器中插入键值对 |
| erase | 删除容器中的键值对 |
| void clear() | 清空容器中有效元素个数 |
| void swap(unordered map&) | 交换两个容器中的元素 |

1.2.6.1:insert与erase
cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>
#include <unordered_map>

void TestModify()
{
	unordered_map<string, int> m1 = { {"abc",1},{"awb",2}};	
	m1.insert({ "ccd",3 });
	m1.insert({ "awd",4 });
	unordered_map<string, int>::iterator it = m1.begin();
	while(it != m1.end())
	{
		cout << it->first << ":" << it->second << endl;
		++it;
	}
	cout << endl;
	m1.erase("abc");
	m1.erase("awd");
	for (auto& e : m1)
	{
		cout << e.first << ":" << e.second << endl;
	}
}

int main()
{
	TestModify();
	return 0;
}
1.2.6.2:clear与swap
cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>
#include <unordered_map>


void TestClearAndSwap() 
{
	unordered_map<string, int> m1 = { {"abc",1},{"awb",2}};
	unordered_map<string, int> m2 = { {"ccd",3},{"awd",4}};
	cout << "交换前" << endl;
	for (const auto& e : m1)
	{
		cout << e.first << ":" << e.second << endl;
	}
	cout << endl;
	for (const auto& e : m2)
	{
		cout << e.first << ":" << e.second << endl;
	}
	cout << "交换后" << endl;
	m1.swap(m2);
	for (const auto& e : m1)
	{
		cout << e.first << ":" << e.second << endl;
	}
	cout << endl;
	for (const auto& e : m2)
	{
		cout << e.first << ":" << e.second << endl;
	}
	m1.clear();
	m2.clear();
	cout << "m1:size:>" << m1.size() << endl;
	cout << "m2:size:>" << m2.size() << endl;
}

int main()
{
	TestClearAndSwap();
	return 0;
}
1.2.7:unordered_map****的桶操作

|------------------------------------|------------------------------|
| 函数声明 | 功能介绍 |
| size_t bucket count()const | 返回哈希桶中桶的总个数 |
| size_t bucket size(size_t n) const | 返回 n 号桶中有效元素的总个数 |
| size_t bucket(const K & key) | 返回元素 key 所在的桶号 |

cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>
#include <unordered_map>


void TestBucketOperation()
{
	unordered_map<string, int> m1 = { {"abc",1},{"awb",2},{"ccd",3},{"awd",4} };
	cout << m1.bucket_count() << endl;
	cout << m1.bucket_size(2) << endl;
	cout << m1.bucket("abc") << endl;
}
int main()
{
	TestBucketOperation();
	return 0;
}

四:unordered_set和set的使用差异

  • unordered_set和set的第一个差异是对key的要求不同,set要求Key支持小于比较,而unordered_set要求Key支持转成整形且支持等于比较,要理解unordered_set的这个两点要求得后续结合哈希表底层实现才能真正理解,也就是说这本质是哈希表的要求。
  • unordered_set和set的第二个差异是迭代器的差异,set的iterator是双向迭代器unordered_set是单向迭代器,其次set底层是红黑树,红黑树是二叉搜索树,走中序遍历是有序的,所以set迭代器的遍历是有序+去重 .而unordered_set底层是哈希表,迭代器遍历是无序+去重。
  • unordered_set和set的第三个差异是性能的差异,整体而言大多数场景下,unordered_set的增删查改更快⼀些,因为 红黑树增删查改效率是O (logN) ,而 哈希表增删查平均效率是O(1) .
cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>
#include <unordered_map>
#include <set>
void Test() 
{
	const size_t N = 1000000;
	unordered_set<int> us;
	set<int> s;
	vector<int> v;
	v.reserve(N);
	srand(time(0));
	for (size_t i = 0; i < N; ++i)
	{
		//v.push_back(rand()); // N⽐较⼤时,重复值⽐较多
		v.push_back(rand() + i); // 重复值相对少
		//v.push_back(i); // 没有重复,有序
	}

	size_t begin1 = clock();
	for (auto e : v)
	{
		s.insert(e);
	}
	size_t end1 = clock();
	cout << "set insert:" << end1 - begin1 << endl;
	size_t begin2 = clock();
	us.reserve(N);
	for (auto e : v)
	{
		us.insert(e);
	}
	size_t end2 = clock();
	cout << "unordered_set insert:" << end2 - begin2 << endl;
	int m1 = 0;
	size_t begin3 = clock();
	for (auto e : v)
	{
		auto ret = s.find(e);
		if (ret != s.end())
		{
			++m1;
		}
	}
	size_t end3 = clock();
	cout << "set find:" << end3 - begin3 << "->" << m1 << endl;
	int m2 = 0;
	size_t begin4 = clock();
	for (auto e : v)
	{
		auto ret = us.find(e);
		if (ret != us.end())
		{
			++m2;
		}
	}
	size_t end4 = clock();
	cout << "unorered_set find:" << end4 - begin4 << "->" << m2 << endl;
	cout << "插入数据个数:" << s.size() << endl;
	cout << "插入数据个数:" << us.size() << endl << endl;
	size_t begin5 = clock();
	for (auto e : v)
	{
		s.erase(e);
	}
	size_t end5 = clock();
	cout << "set erase:" << end5 - begin5 << endl;
	size_t begin6 = clock();
	for (auto e : v)
	{
		us.erase(e);
	}
	size_t end6 = clock();
	cout << "unordered_set erase:" << end6 - begin6 << endl << endl;
}


int main()
{
	Test();
	return 0;
}

五:unordered_map和map的使用差异

  • unordered_map和map的第⼀个差异是对key的要求不同,map要求Key支持小于比较,而
    unordered_map要求Key支持转成整形且支持等于比较,要理解unordered_map的这个两点要求得后续结合哈希表底层实现才能真正理解,也就是说这本质是哈希表的要求。
  • unordered_map和map的第二个差异是迭代器的差异,map的iterator是双向迭代器,unordered_map是单向迭代器,其次map底层是红黑树,红黑树是二叉搜索树,走中序遍历是有序的 ,所以map迭代器遍历是Key有序 + 去重。而 unordered_map底层是哈希表,迭代器遍历是Key无序+去重.
  • unordered_map和map的第三个差异是性能的差异,整体而言大多数数场景下unordered_map的增删查改更快⼀些,因为红黑树树增删查改效率是O ( logN ) ,而哈希表增删查平均效率是O (1)具体可以参看下⾯代码的演示的对比差异。
cpp 复制代码
#include <iostream>
using namespace std;
#include <unordered_set>
#include <unordered_map>
#include <map>
#include <set>
void Test() 
{
	const size_t N = 1000000;
	unordered_map<int, int> um;
	map<int, int> m;
	vector<int> v;
	v.reserve(N);
	srand(time(0));
	for (size_t i = 0; i < N; ++i)
	{
		//v.push_back(rand()); // N比较大时,重复值比较多
		v.push_back(rand() + i); // 重复值相对少
		//v.push_back(i); // 没有重复,有序
	}

	size_t begin1 = clock();
	for (auto e : v)
	{
		m.insert({e,e});
	}
	size_t end1 = clock();
	cout << "map insert:" << end1 - begin1 << endl;
	size_t begin2 = clock();
	um.reserve(N);
	for (auto e : v)
	{
		um.insert({e,e});
	}
	size_t end2 = clock();
	cout << "unordered_map insert:" << end2 - begin2 << endl;
	int m1 = 0;
	size_t begin3 = clock();
	for (auto e : v)
	{
		auto ret = m.find(e);
		if (ret != m.end())
		{
			++m1;
		}
	}
	size_t end3 = clock();
	cout << "set find:" << end3 - begin3 << "->" << m1 << endl;
	int m2 = 0;
	size_t begin4 = clock();
	for (auto e : v)
	{
		auto ret = um.find(e);
		if (ret != um.end())
		{
			++m2;
		}
	}
	size_t end4 = clock();
	cout << "unorered_set find:" << end4 - begin4 << "->" << m2 << endl;
	cout << "插入数据个数:" << m.size() << endl;
	cout << "插入数据个数:" << um.size() << endl << endl;
	size_t begin5 = clock();
	for (auto e : v)
	{
		m.erase(e);
	}
	size_t end5 = clock();
	cout << "map erase:" << end5 - begin5 << endl;
	size_t begin6 = clock();
	for (auto e : v)
	{
		um.erase(e);
	}
	size_t end6 = clock();
	cout << "unordered_map erase:" << end6 - begin6 << endl << endl;
}


int main()
{
	Test();
	return 0;
}
相关推荐
艾莉丝努力练剑2 小时前
剑指巅峰,磨砺芳华:我的 CSDN 创作一周年深度总结
linux·运维·服务器·c++·学习
t***5442 小时前
如何在Dev-C++中设置Clang编译参数
开发语言·c++
csbysj20203 小时前
PHP If...Else 语句详解
开发语言
清水白石00810 小时前
Python 编程实战全景:从基础语法到插件架构、异步性能与工程最佳实践
开发语言·python·架构
Halo_tjn12 小时前
Java 基于字符串相关知识点
java·开发语言·算法
梦想的颜色12 小时前
java 利用redis来限制用户频繁点击
java·开发语言
报错小能手12 小时前
Swift 并发 Combine响应式框架
开发语言·ios·swift
万法若空13 小时前
C++ <memory> 库全方位详解
开发语言·c++
代码中介商13 小时前
C++ 类型转换深度解析:static_cast、dynamic_cast、const_cast、reinterpret_cast
开发语言·c++