C++ 这个std::set初始化是如何工作的?
我在理解std::set初始化如何工作时遇到了一些困难。我在函数中有以下代码:C++ 这个std::set初始化是如何工作的?,c++,stdset,C++,Stdset,我在理解std::set初始化如何工作时遇到了一些困难。我在函数中有以下代码: std::map<int, int> my_map = { {16, 24}, {19, 29}, {15, 23}, {14, 22}, {13, 21}, {17, 28}, }; typedef std::function<bool(std::pair<int, int>, std::pair<int, int>
std::map<int, int> my_map = {
{16, 24},
{19, 29},
{15, 23},
{14, 22},
{13, 21},
{17, 28},
};
typedef std::function<bool(std::pair<int, int>, std::pair<int, int>)> comparefunction;
comparefunction compare =
[](std::pair<int, int> a, std::pair<int, int> b){
if(lessthan(a,b))
std::cout << "a" << std::endl;
else
std::cout << "b" << std::endl;
return true;
};
std::set<std::pair<int, int>, comparefunction>
values(my_map.begin(), my_map.end(), compare);
std::map my\u map={
{16, 24},
{19, 29},
{15, 23},
{14, 22},
{13, 21},
{17, 28},
};
typedef std::函数compareffunction;
比较函数比较=
[](标准::对a,标准::对b){
if(小于(a,b))
std::cout我想让你困惑的是映射迭代器的行为。在映射上迭代(从my\u map.begin()
到my\u map.end()
)意味着遍历类型为std::pair
(对于键类型K
和映射值类型V
);在您的例子中,它是std::pair
。所以实际上,映射非常类似于这些对的集合
现在,您正在使用的集合的构造函数,如@AlgirdasPreidžius和@IgorTandetnik suggest,是集合中的(=从开始迭代器到结束迭代器),因此您得到了一组对
最后,lambda可能会改变元素相同的规则
现在有意义了吗
PS 1:您可能更喜欢
unordered\u set
和unordered\u map
;尝试一下,看看什么更适合您的需要。您正在用一些值初始化一个集合。这些值恰好来自于您的映射,但寻找它们并不重要。重要的是将给出集合的构造函数使用以下值(这些值实际上是
std::pair
s,但大括号表示法很方便):
[在这一点上,有人可能会注意到,我不是按照映射初始化的顺序,而是按照它们的第一个坐标(映射的键)进行排序。这是因为映射是有序的,所以begin()
到end()
从最低的键到最高的键遍历映射。]
那么会发生什么呢?集合的构造函数创建一个集合,然后将这些元素添加到其中。第一个元素({13,21}
)没有问题;将元素添加到空集合很容易
不过,第二个元素需要放在集合中维护顺序的位置。也就是说,构造函数需要知道新元素({14,22}
)的比较是否小于现有元素({13,21}
)。它是如何发现的?它调用您给它的函数:比较({14,22},{13,21})
。返回true,因此新元素在集合中位于旧元素之前。注意:参数的顺序不是固定的;因为输出是“b”,我猜这就是使用的顺序 添加第三个元素(
{15,23}
)类似。构造函数需要知道它在集合中的位置,因此它从一个现有元素开始(实现者选择从哪个开始)并使用该元素和新元素调用函数。函数返回true,因此新元素将置于现有元素之前。根据选择的元素,可能需要再次调用compare
,以确定新元素在集合中位于第一位。注意:如果实现者选择了其他顺序的参数,新元素将排在集合的最后;如果发生这种情况,您可能会看到“a”而不是“b” 剩下的三个元素也是如此 想混淆构造函数吗?让lambda返回false而不是true。这将使构造函数确信所有对都是等价的,这意味着在用六个元素构造之后,集合将只包含一个(
{13,21}
)。在这种情况下,将“set”更改为“multiset”将允许添加其他元素
实际上,构造函数可能会被总是返回true的函数所迷惑。最好让它返回a是否被认为小于b。您是否尝试过查看文档中可能的构造函数?我不确定我是否完全理解您困惑的本质。您正在使用谢谢,我意识到它使用了范围构造函数,但我看不到映射的迭代器如何自动与lambda函数一起工作。什么是“魔法”当我初始化集合时,在它后面?
std::set
将其元素按顺序排序。为了做到这一点,它需要对它们进行比较。因此调用比较函数。否则为什么您认为您提供了一个比较函数?如果从未调用它,它不是毫无意义吗?您的比较函数总是返回true
,这是意味着集合
在尝试使用比较器时会感到困惑。您应该返回lessthan
的结果(假设这是一个有效的比较函数,如a
或std::less
),为了更好地调试,您可能还希望打印出对的实际值,而不仅仅是“a”
和“b”
。非常感谢您,这确实帮助我们澄清了问题,非常感谢
{13,21} {14,22} {15,23} {16,24} {17,28} {19,29}