C ++ STL集的复杂模板参数类型

时间:2011-08-27 06:05:13

标签: c++ stl set

我正在使用复杂的模板参数类型实现STL集。当插入到集合中时,我希望集合使用我为我的类型定义的小于运算符。我希望最小化我的类型的对象实例化的数量。看来我不能同时拥有这两者。

下面我有两个最小的例子,每个例子都使用相同的C ++类。

#include <iostream>
#include <set>

using namespace std;

class Foo {
    public:
        Foo(int z);
        Foo(const Foo &z);
        bool operator<(const Foo &rhs) const;
        int a;
};

Foo::Foo(int z)
{
    cout << "cons" << endl;
    a = z;
}

Foo::Foo(const Foo &z)
{
    cout << "copy cons" << endl;
    a = z.a;
}

bool
Foo::operator<(const Foo &rhs) const
{
    cout << "less than" << endl;
    return a < rhs.a;
}

这是我的第一个主要的():

int
main(void)
{
    set<Foo> s;

    s.insert(*new Foo(1));
    s.insert(*new Foo(2));
    s.insert(*new Foo(1));

    cout << "size: " << s.size() << endl;

    return 0;
}

这很好,因为它使用的比我为我的类定义的少,因此集合的大小正确为两。但这很糟糕,因为每次插入集合都需要实例化两个对象(构造函数,复制构造函数)。

$ ./a.out
cons
copy cons
cons
less than
less than
less than
copy cons
cons
less than
less than
less than
size: 2

这是我的第二个主要():

int
main(void)
{
    set<Foo *> s;

    s.insert(new Foo(1));
    s.insert(new Foo(2));
    s.insert(new Foo(1));

    cout << "size: " << s.size() << endl;

    return 0;
}

这很好,因为插入只需要一个对象实例化。但这很糟糕,因为它实际上是一组指针,因此就我的类型而言,集合成员的唯一性已经消失。

$ ./a.out
cons
cons
cons
size: 3

我希望有一些我缺少的信息。我可以同时进行最小的对象实例化和适当的排序吗?

3 个答案:

答案 0 :(得分:1)

您将从中获取副本:*new Foo(1)

创建此结构:

template<typename T>
struct PtrLess
{
    bool operator()(const T *a, const T *b) const
    {
        return *a < *b;
    }
};

使地图看起来像set<Foo*, PtrLess<Foo>> s;,然后像s.insert(new Foo(1));一样添加Foo 请注意 *

否则,当地图为Foo项创建容器时,由于它是在foo容器定义中分配的,因此地图必须将提供的值复制到其内部Foo对象中。

答案 1 :(得分:1)

标准容器存储已添加项目的副本。如果您希望set存储对象而不是指针,则应该执行以下操作,否则您将创建内存泄漏,因为通过new分配的对象永远不会通过相应的方式释放delete

int main()
{
    set<Foo> s;

    s.insert(Foo(1));
    s.insert(Foo(2));
    s.insert(Foo(1));

    cout << "size: " << s.size() << endl;

    return 0;
}

如果要最小化实例化的临时对象的数量,只需使用一个临时对象:

int main()
{
    set<Foo> s;

    Foo temp(1);
    s.insert(temp);
    temp.a = 2;
    s.insert(temp);
    temp.a = 1;
    s.insert(temp);

    cout << "size: " << s.size() << endl;

    return 0;
}

此代码段的输出(通过ideone)是:

cons
copy cons 
less than
less than
less than
copy cons
less than
less than
less than
size: 2

通常,我更愿意将实际对象存储在set<Foo>而不是指向set<Foo*>中对象的指针,因为对象所有权不会出现问题(谁/何时{{1}并且需要调用new),分配的内存总量较小(对于delete项需要N而不是N*sizeof(Foo)字节)和数据访问更快(因为没有额外的指针间接)。

希望这有帮助。

答案 2 :(得分:0)

这是对@Mranz answer的扩展。而不是处理原始指针,将指针放在std::unique_ptr

#include <memory>

using namespace std;

template<typename T>
struct PtrLess
{
    bool operator()(const T& a, const T& b) const
    {
        return *a < *b;
    }
};


int
main(void)
{
    set<unique_ptr<Foo>, PtrLess<unique_ptr<Foo>>> s;

    s.insert(unique_ptr<Foo>(new Foo(1)));
    s.insert(unique_ptr<Foo>(new Foo(2)));
    s.insert(unique_ptr<Foo>(new Foo(1)));

    cout << "size: " << s.size() << endl;

    return 0;
}