【问题标题】:Is this legal to avoid set from creating actual copies of Comparator object避免设置创建 Comparator 对象的实际副本是否合法
【发布时间】:2014-04-08 16:17:35
【问题描述】:

在这样的代码中:

Comparator comp(3);

set<string, Comparator> s1(comp);
set<string, Comparator> s2(comp);
set<string, Comparator> s3(comp);
set<string, Comparator> s4(comp); 

Comparator 的实际实例(即 comp)在每次创建集合对象时复制为 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;
}

提前致谢。

【问题讨论】:

  • '所以我们想知道这在 C++ 中是否合法'至少它compiles fine,并且做到了恕我直言。
  • @πάνταῥεῖ:这在 C++ 中根本不是一个有效的论点
  • 我感觉这是一个脆弱的解决方案;比较器通常被认为是无状态的或将其状态外部化(例如 pimpl 所做的);我不确定标准是怎么说的,即是否需要一个集合来存储其比较器的副本或尊重它是一个参考。不幸的是,我现在没有时间研究它。
  • 我很确定这是不合法的...难道比较器类型至少必须是可复制的吗? [编辑:规范说它必须是可交换的,引用是否可交换?]

标签: c++ templates stl set functor


【解决方案1】:

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

最后请注意,规范的 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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 2014-01-29
    • 2014-10-31
    • 2016-08-08
    • 1970-01-01
    相关资源
    最近更新 更多