在C++ STL中的unordered_set emplace()函数
C++是一种面向对象的编程语言,STL是其中不可或缺的一个元素,它为C++提供了许多常用数据结构和算法。unordered_set是C++ STL提供的一个用于存储元素的唯一集合容器,它的特点在于元素的存储不需要遵守特定顺序,同时也不允许出现重复元素。在这篇文章中,我们将介绍unordered_set中的emplace()函数及其用法。
unordered_set的基本用法
在使用unordered_set之前,需要首先包含相应的头文件:
#include <unordered_set>
unordered_set的定义方式如下:
std::unordered_set<int> mySet;
这表示创建了一个名为mySet的unordered_set对象,用于存储int类型的元素。接下来,我们可以使用insert()函数将元素插入到mySet中:
mySet.insert(1);
mySet.insert(2);
mySet.insert(3);
mySet.insert(4);
以上代码将1、2、3、4四个元素依次插入到mySet中。需要注意的是,unordered_set中不允许出现重复元素,因此如果尝试插入重复元素,将不会发生任何事情。
mySet.insert(1);
以上代码将不会导致任何变化,mySet中仍然只有四个元素。此外,unordered_set的存储方式不受限于特定顺序,因此在遍历unordered_set时不会按照元素插入的顺序输出。
for (auto it = mySet.begin(); it != mySet.end(); ++it) {
std::cout << *it << " ";
}
以上代码将随机输出1、2、3、4四个元素,顺序不一定与插入顺序相同。
unordered_set的emplace()函数
emplace()函数是C++11标准中为unordered_set新增的一个函数,它与insert()函数类似,都用于将元素插入到unordered_set中。但是,emplace()函数相对于insert()函数有着更高的效率,并且可读性更好。
emplace()函数的最基本用法如下:
std::unordered_set<std::string> mySet;
mySet.emplace("str1");
mySet.emplace("str2");
mySet.emplace("str3");
mySet.emplace("str4");
以上代码将4个字符串依次插入到mySet中。需要注意的是,unordered_set中每个元素都是一个键值对,其中键为元素的值,值为一个空的占位符类型。因此,插入元素时需要使用emplace函数并传入元素的值,而不是insert()函数中需要传入键值对类型的元素。
在使用emplace()函数时,还可以在插入元素时同时指定值。示例代码如下:
struct Student {
int id;
std::string name;
};
std::unordered_set<Student> myStudents;
myStudents.emplace( {1, "Tom"} );
myStudents.emplace( {2, "Jerry"} );
以上代码用于将两个student对象插入到myStudents中,并为每个对象分别指定id和name两个属性。这里需要注意的是,在为Student对象的属性赋值时需要使用花括号,并依次指定每个属性的值。
如果要将重复元素插入到unordered_set中,可以使用emplace_hint()函数,使用方法与insert_hint()函数基本相同。
std::unordered_set<int> mySet = {1, 2, 3, 4};
auto it = mySet.emplace_hint( mySet.begin(), 2 );
以上代码用于将数字2插入到mySet中,并返回插入元素的迭代器。需要注意的是,在使用emplace_hint()函数时需要指定一个迭代器,它表示元素插入的位置。在这里,我们使用了mySet.begin()作为位置,因此2将会插入到mySet的最前面。
emplace()函数的性能
emplace()函数相对于insert()函数具有更高的性能,这是因为emplace()函数将元素直接构造在unordered_set中,而不是先在外部构造元素再插入到集合中。
为了比较emplace()函数和insert()函数的性能,我们可以写一个小实验,分别使用这两个函数向unordered_set中插入1000万个元素,并记录时间消耗。
#include <iostream>
#include <chrono>
#include <unordered_set>
int main() {
std::unordered_set<int> mySet;
// 使用insert()函数插入1000万个元素
auto start = std::chrono::system_clock::now();
for (int i = 0; i < 10000000; ++i) {
mySet.insert(i);
}
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> diff_insert = end-start;
std::cout << "Using insert() function: " << diff_insert.count() << " seconds\n";
// 使用emplace()函数插入1000万个元素
start = std::chrono::system_clock::now();
for (int i = 0; i < 10000000; ++i) {
mySet.emplace(i);
}
end = std::chrono::system_clock::now();
std::chrono::duration<double> diff_emplace = end-start;
std::cout << "Using emplace() function: " << diff_emplace.count() << " seconds\n";
return 0;
}
运行以上代码,我们可以看到emplace()函数比insert()函数快了近两秒钟。这是一个非常明显的性能提升,特别是对于需要频繁插入元素的场景。
结论
unordered_set是C++ STL中非常常用的一个容器,它可以存储唯一的元素,并且不要求元素的存储顺序。在使用unordered_set时,emplace()函数是一个非常推荐的插入元素的方式,它能够更高效地构造元素。此外,emplace()函数还具有更可读的代码表达能力,能够更清晰地表达程序员的意图。但是,在需要控制插入元素的位置时,可能需要使用emplace_hint()函数或者insert_hint()函数。