这是合法的,以避免设置创建Comparator对象的实际副本

Iss*_* T. 5 c++ templates stl set functor

在这样的代码中:

Comparator comp(3);

set<string, Comparator> s1(comp);
set<string, Comparator> s2(comp);
set<string, Comparator> s3(comp);
set<string, Comparator> s4(comp); 
Run Code Online (Sandbox Code Playgroud)

比较器的实际实例(即comp)在每次创建set对象时被复制为cpp引用状态

容器保留alloc和comp的内部副本,用于分配存储并在整个生命周期内对元素进行排序.

所以我们想知道这在C++中是否合法

#include <set>
#include <iostream>

struct A {
    int i = 0;
    bool operator()(int a, int b)
    {
        ++i;
        return a < b;
    }
};

int main()
{    
    A a;
    std::set<int, A&> s1( {1, 2, 3}, a);
    std::set<int, A&> s2( {4, 5, 6}, a);
    std::cout << a.i;
}
Run Code Online (Sandbox Code Playgroud)

提前致谢.

Mar*_*k B 4

我无法在标准中找到禁止使用引用类型作为比较函数的措辞。因此,这似乎是合法的。请注意,某些事情(例如默认构造这样的集合)将被禁止,因为您的比较类型不可默认构造。

最后请注意,规范的 C++ 方法不是这样做,而是在外部维护状态。当您采取这种方法时,您就完全清楚自己在做什么并保证安全:

#include <set>
#include <iostream>

struct A {
    int& i_;
    explicit A(int& state) : i_(state) { }
    bool operator()(int a, int b)
    {
        ++i_;
        return a < b;
    }
};

int main() {
    int i;
    std::set<int, A> s1( {1, 2, 3}, A(i));      
    std::set<int, A> s2( {4, 5, 6}, A(i));        
    std::cout << i << endl;
}
Run Code Online (Sandbox Code Playgroud)