std :: set :: find vs std :: find on std :: set with const

时间:2015-09-17 08:40:45

标签: c++ c++11

我写了一些(工作)测试代码,但我不明白为什么在test1函数中我只能传递int* const作为参数,而在test2函数中我可以通过一个const int*。如果我将const int*传递给test1,我会收到丢弃限定符错误。

在我的研究中,我发现std::findset::find都有一个const版本,所以我看不出它们为什么表现不同。我也尝试使用boost::container::flat_set而不是std::set,我得到了相同的结果。 有人可以解释一下吗?

class myClass
{
public:
    myClass() {};
    ~myClass() {};

    void add(int* ref)
    {
        this->_ref.insert(ref);
    };

    bool test1(int* const ref) const
    {
        return ( this->_ref.find(ref) != this->_ref.end() );
    }

    inline
    bool test2(const int* ref) const
    {
        return ( std::find(this->_ref.begin(), this->_ref.end(), ref) != this->_ref.end() );
    }

    std::set<int*> _ref;
};

int main()
{
    myClass test;
    test.add(new int(18));
    test.add(new int(35));
    test.add(new int(78));
    test.add(new int(156));

    std::cout<<test.test1(0)<<std::endl;
    std::cout<<test.test1(*test._ref.begin())<<std::endl;

    std::cout<<test.test2(0)<<std::endl;
    std::cout<<test.test2(*test._ref.begin())<<std::endl;

    return 0;
}

2 个答案:

答案 0 :(得分:2)

容器std::set<int*>只有同类查找,因此您只能通过将密钥与相同类型的值进行比较来搜索密钥:{{1} },findcount。当然,类型erase的值与const int*的类型不同,因此您的int*代码会尝试将前者转换为后者,这不是允许的转换。

容器只能以同类方式使用这一事实从一开始就是C ++的一个缺点,而且当你有一个带有test2键的地图并希望看起来时,更多非常不希望的转换的例子就是带有作为字符串文字提供的键的元素。您总是必须构造动态std::string对象,即使std::string为字符串文字提供了比较运算符。

因此,从C ++ 14开始,您还可以通过拼写std::string来创建具有非均匀查找的集合(或映射)。使用这样的容器,循环函数成为模板,您确实可以比较不同类型的值(将转换逻辑留给底层的std::set<int*, std::less<>> - 运算符)。但请注意,<需要对指针提供严格的弱排序,而std::less<int*>则不是,因此您最终可能会遇到未定义的行为。

答案 1 :(得分:0)

set::find()以O(logN)给出答案,而std::find()以O(N)给出答案。

类似地,map::find()以O(logN)给出答案,而std::find()以O(N)给出答案。