向 std::map<> 添加对象和自定义比较
Adding objects to, and custom comparisons for std::map<>
我发现某些 std::map<>
参考 material 有时有点难以理解。
当我向地图添加一个对象时,它会像 MFC 的 CMap<>
那样复制该对象吗?或者它是否拥有我添加的对象?
我正在尝试创建自定义比较器。但是,我的密钥是 class 类型。我如何指定应该向比较器传递对关键对象而不是对象本身的引用?或者将我的比较器声明为接收参考就足够了吗?
我不确定我是否完全理解你想知道的,但让我尝试分享我的经验。
如果"Own the object"意思是将值复制到map自己的内存中space,是的。
向 std::map 插入一个项目,将至少占用 size(pair) 内存,并在擦除时自动销毁它们。 (忽略stl的内存分配缓冲区)
如果您需要 "A reference",请考虑改用 std::shared_ptr
ps:详细图的内存:How can i estimate memory usage of std::map?
比较函数接受参考值,大多数情况下你应该使用它。
例子
class CObjectKey
{
public:
CObjectKey(int type, int index)
: type_(type), index_(index)
{
}
bool operator <(const CObjectKey& right) const
{
if (this == &right)return false;
return (type_ < right.type_) || (type_ == right.type_ && index_ < right.index_);
}
private:
int type_;
int index_;
};
int main()
{
std::map<CObjectKey, std::string> map1;
map1.emplace(CObjectKey(1, 2), "val_1_2");
map1.emplace(CObjectKey(1, 3), "val_1_3");
std::cout << "Hello World! " << map1[CObjectKey(1,3)] << std::endl;
}
std::map
(或任何其他标准容器)中包含的所有对象的生命周期都由容器管理。容器包含对象。如果您希望容器包含指针,您需要这样声明它。
例如在下面的代码中,
struct MyType { /*...*/ };
MyType my_object;
std::map<int, MyType> my_map;
my_map.insert({42, my_object});
复制了my_object
,但在下面
struct MyType { /*...*/ };
MyType my_object;
std::map<int, MyType*> my_map;
my_map.insert({42, &my_object});
唯一被复制的是指向 my_object
的 指针 ,而不是 my_object
本身。在这种情况下,地图仍然管理其包含对象的生命周期,但那些包含的对象只是指针,您有责任确保指向的对象比指向它们的指针更长寿。最好的方法通常是使用标准智能指针 class 模板之一:std::unique_ptr
或 std::shared_ptr
,具体取决于您的需要。
对于你问题的第二部分,是的,只要让你的自定义比较器通过引用接受值就足够了。 std::map
将其中包含的实际对象传递给比较器。
我发现某些 std::map<>
参考 material 有时有点难以理解。
当我向地图添加一个对象时,它会像 MFC 的
CMap<>
那样复制该对象吗?或者它是否拥有我添加的对象?我正在尝试创建自定义比较器。但是,我的密钥是 class 类型。我如何指定应该向比较器传递对关键对象而不是对象本身的引用?或者将我的比较器声明为接收参考就足够了吗?
我不确定我是否完全理解你想知道的,但让我尝试分享我的经验。
如果"Own the object"意思是将值复制到map自己的内存中space,是的。 向 std::map
插入一个项目,将至少占用 size(pair ) 内存,并在擦除时自动销毁它们。 (忽略stl的内存分配缓冲区) 如果您需要 "A reference",请考虑改用 std::shared_ptr
ps:详细图的内存:How can i estimate memory usage of std::map?
比较函数接受参考值,大多数情况下你应该使用它。
例子
class CObjectKey
{
public:
CObjectKey(int type, int index)
: type_(type), index_(index)
{
}
bool operator <(const CObjectKey& right) const
{
if (this == &right)return false;
return (type_ < right.type_) || (type_ == right.type_ && index_ < right.index_);
}
private:
int type_;
int index_;
};
int main()
{
std::map<CObjectKey, std::string> map1;
map1.emplace(CObjectKey(1, 2), "val_1_2");
map1.emplace(CObjectKey(1, 3), "val_1_3");
std::cout << "Hello World! " << map1[CObjectKey(1,3)] << std::endl;
}
std::map
(或任何其他标准容器)中包含的所有对象的生命周期都由容器管理。容器包含对象。如果您希望容器包含指针,您需要这样声明它。
例如在下面的代码中,
struct MyType { /*...*/ };
MyType my_object;
std::map<int, MyType> my_map;
my_map.insert({42, my_object});
复制了my_object
,但在下面
struct MyType { /*...*/ };
MyType my_object;
std::map<int, MyType*> my_map;
my_map.insert({42, &my_object});
唯一被复制的是指向 my_object
的 指针 ,而不是 my_object
本身。在这种情况下,地图仍然管理其包含对象的生命周期,但那些包含的对象只是指针,您有责任确保指向的对象比指向它们的指针更长寿。最好的方法通常是使用标准智能指针 class 模板之一:std::unique_ptr
或 std::shared_ptr
,具体取决于您的需要。
对于你问题的第二部分,是的,只要让你的自定义比较器通过引用接受值就足够了。 std::map
将其中包含的实际对象传递给比较器。