我正在使用复杂的模板参数类型实现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
我希望有一些我缺少的信息。我可以同时进行最小的对象实例化和适当的排序吗?
答案 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;
}