可以std :: set保持指针键而不是键本身吗? [英] can std::set hold pointers to keys instead of the keys themselves?

查看:92
本文介绍了可以std :: set保持指针键而不是键本身吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从来没有遇到任何问题在STL

容器中存储指针,例如std :: vector和std :: map。好处

存储指针而不是对象本身

主要是节省内存资源和性能(STL

容器保存*副本*的什么通过

insert()方法传递给他们。


但是,我不知道如何使用

std :: set。由于各种原因,我不能在我的应用程序中使用vector或

map。但我想使用

相同的优化我一直用STL

容器,这让他们存储指向

项目,而不是项目本身。


特别是,下面的代码片段编译和

工作得很漂亮(尽管效率不高):
std :: set< CItemKey,std :: less< CItemKey> > TItemKeys;

typedef TItemKeys :: const_iterator TItemKeysConstIterator;

typedef TItemKeys :: iterator TItemKeysIterator;


TItemKeys m_items;


const CItem * CContainer :: getItem(const CItemKey& rItemKey)const

{

TItemKeysConstIterator it = m_items.find(rItemKey);


if(it!= m_items.end())

返回static_cast< const CItem *>(it-> getOwner());

else

返回(NULL);

}

============ ====================================== ====

但是,当我修改这个基于指针的

(注意细微差别)时,它甚至没有
编译!它在find()语句中失败,因为

无法转换参数的类型(或

返回值):


================工作代码SNIPPET ================

typedef std :: set< ; CItemKey *,std :: less< CItemKey> > TItemKeys;

typedef TItemKeys :: const_iterator TItemKeysConstIterator;

typedef TItemKeys :: iterator TItemKeysIterator;


TItemKeys m_items;


const CItem * CContainer :: getItem(const CItemKey& rItemKey)const

{

TItemKeysConstIterator it = m_items.find(rItemKey);


if(it!= m_items.end())

返回static_cast< const CItem *>(it-> getOwner());

else

返回(NULL);

}

============ ====================================== ====


我做错了什么?


我也尝试将m_items.find(rItemKey)修改为

m_items.find(& rItemKey)但是这也没有帮助。

显然我在这里碰到了精神障碍。


有没有办法完成我想要的工作? />
实现(在一组中存储指针)?或者这个

从根本上是不正确的,因为定义必须

包含键,而不是键的指针?


谢谢。

I never had any problems storing pointers in STL
containers such std::vector and std::map. The benefit
of storing pointers instead of the objects themselves
is mainly saving memory resources and performance (STL
containers hold *copies* of what''s passed to them via
the insert() method).

However, I am not sure how to accomplish that using
std::set. For various reasons, I cannot use vector or
map in my application. But I would like to use the
same optimization I have always used with STL
containers, which is letting them store pointers to
the items, not the items themselves.

In particular, the following code snippet compiles and
works beautifully (albeit no so efficient):

================ WORKING CODE SNIPPET ================
typedef std::set<CItemKey, std::less<CItemKey> > TItemKeys;
typedef TItemKeys::const_iterator TItemKeysConstIterator;
typedef TItemKeys::iterator TItemKeysIterator;

TItemKeys m_items;

const CItem* CContainer::getItem(const CItemKey& rItemKey) const
{
TItemKeysConstIterator it = m_items.find(rItemKey);

if (it != m_items.end())
return static_cast<const CItem*>(it->getOwner());
else
return (NULL);
}
================================================== ====
However, when I modify this to be pointer based
(notice the subtle difference), it does not even
compile! It fails on the find() statement for
inability to convert the type of the parameter (or the
return value):

================ WORKING CODE SNIPPET ================
typedef std::set<CItemKey*, std::less<CItemKey> > TItemKeys;
typedef TItemKeys::const_iterator TItemKeysConstIterator;
typedef TItemKeys::iterator TItemKeysIterator;

TItemKeys m_items;

const CItem* CContainer::getItem(const CItemKey& rItemKey) const
{
TItemKeysConstIterator it = m_items.find(rItemKey);

if (it != m_items.end())
return static_cast<const CItem*>(it->getOwner());
else
return (NULL);
}
================================================== ====

What am I doing wrong?

I also tried modifying m_items.find(rItemKey) to
m_items.find(&rItemKey) but that doesn''t help either.
Obviously I ran into a mental block here.

Is there a way to accomplish what I am trying to
achieve (storing pointers in a set)? Or is this
fundamentally incorrect, as set by definition must
contain keys, not pointers to keys?

Thanks.

推荐答案

da **** @ my-deja.com 写道:
[..]
然而,当我将其修改为基于指针的
时(注意细微差别),它确实如此甚至没有编译!它无法在find()语句中无法转换参数的类型(或
返回值):

========== ======工作代码SNIPPET ================


您的意思是非工作代码SNIPPET吗? br />

typedef std :: set< CItemKey *,std :: less< CItemKey> > TItemKeys;
typedef TItemKeys :: const_iterator TItemKeysConstIterator;
typedef TItemKeys :: iterator TItemKeysIterator;

TItemKeys m_items;

const CItem * CContainer :: getItem (const CItemKey& rItemKey)const
{TItemKeysConstIterator it = m_items.find(rItemKey);


诀窍在于你正在寻找''m_items''中的元素

_points_到同一个_value_和''rItemKey'' ,但''find''只为相同的_pointer_看起来是

。将它更改为


TItemKeysConstIterator it = m_items.find(& rItemKey);


应该帮助它编译,但我不是看它工作得很好因为

你传递的物品不太可能和套装中的任何

物品具有相同的地址。


您可能希望使用''std :: find''和您自己的自定义谓词

,它将取消引用指针并将其与您需要的值进行比较

需要。

if(it!= m_items.end())
返回static_cast< const CItem *>(it-> getOwner());
else
return(NULL);
}
=================================== =============== ====

我做错了什么?

我也尝试修改m_items.find(rItemKey) )对于m_items.find(& rItemKey),但这也没有帮助。


以什么方式没有帮助?它是否可以编译?

显然我在这里遇到了一个心理障碍。

有没有办法完成我想要实现的目标(将指针存储在一个组)?或者这是否根本不正确,因为定义必须包含键,而不是键指针?
[..]
However, when I modify this to be pointer based
(notice the subtle difference), it does not even
compile! It fails on the find() statement for
inability to convert the type of the parameter (or the
return value):

================ WORKING CODE SNIPPET ================
Did you mean "NON-WORKING CODE SNIPPET"?

typedef std::set<CItemKey*, std::less<CItemKey> > TItemKeys;
typedef TItemKeys::const_iterator TItemKeysConstIterator;
typedef TItemKeys::iterator TItemKeysIterator;

TItemKeys m_items;

const CItem* CContainer::getItem(const CItemKey& rItemKey) const
{
TItemKeysConstIterator it = m_items.find(rItemKey);
The trick is that you''re looking for the element in ''m_items'' that
_points_ to the same _value_ as ''rItemKey'', but ''find'' only looks
for the same _pointer_. Changing it to

TItemKeysConstIterator it = m_items.find(&rItemKey);

should help it compile, but I don''t see it work very well because
the item you pass will very unlikely have the same address as any
item in the set.

You probably want to use ''std::find'' with your own, custom predicate
that will dereference the pointer and compare it to the value you
need.
if (it != m_items.end())
return static_cast<const CItem*>(it->getOwner());
else
return (NULL);
}
================================================== ====

What am I doing wrong?

I also tried modifying m_items.find(rItemKey) to
m_items.find(&rItemKey) but that doesn''t help either.
Doesn''t help in what way? Does it compile?
Obviously I ran into a mental block here.

Is there a way to accomplish what I am trying to
achieve (storing pointers in a set)? Or is this
fundamentally incorrect, as set by definition must
contain keys, not pointers to keys?




嗯,你在扭曲定义。你的套装不包含

_pointers_to_keys_。它包含_pointers_。它们都是价值

和钥匙。现在,如果您使用某种自定义比较器来将您的存储值与解除引用相比较,那么您可能会获得更接近实现所需内容的
。看看std :: set的第二个模板

参数。


V



Well, you''re twisting the definition. Your set doesn''t contain
_pointers_to_keys_. It contains _pointers_. They are both values
and keys. Now, if you had some kind of custom comparator to make
your stored values compared with dereferencing, then you might get
closer to achieving what you want. Look at the second template
argument for std::set.

V


da **** @ my-deja.com 写道:
da****@my-deja.com wrote:
我从来没有过在STL
容器中存储指针的任何问题,例如std :: vector和std :: map。存储指针而不是对象本身的好处
主要是节省内存资源和性能(STL
容器保存*副本*通过
传递给他们的内容insert()方法)。

但是,我不知道如何使用
std :: set来实现。由于各种原因,我不能在我的应用程序中使用矢量或
地图。但是我想使用与STL
容器一直使用的相同优化,这让他们存储了指向项目的指针,而不是项目本身。
工作得很漂亮(尽管效率不高):

================工作代码SNIPPET ================
typedef std :: set< CItemKey,std :: less< CItemKey> > TItemKeys;
typedef TItemKeys :: const_iterator TItemKeysConstIterator;
typedef TItemKeys :: iterator TItemKeysIterator;

TItemKeys m_items;

const CItem * CContainer :: getItem (const CItemKey& rItemKey)const
{TItemKeysConstIterator it = m_items.find(rItemKey);

if(it!= m_items.end())
返回static_cast< const CItem *>(it-> getOwner());

返回(NULL);
}
========== ======================================== ====

但是,当我将其修改为基于指针的
时(注意细微差别),它甚至没有编译!它无法在find()语句中无法转换参数的类型(或
返回值):

========== ======工作代码SNIPPET ================
typedef std :: set< CItemKey *,std :: less< CItemKey> > TItemKeys;


您正在使用产生类型不匹配的比较函数。

使用std :: less< T *>或类似


pointee_comapare(CItemKey const * a,CItemKey const b * b){

return(* a)< (* b);

}

typedef TItemKeys :: const_iterator TItemKeysConstIterator;
typedef TItemKeys :: iterator TItemKeysIterator;

TItemKeys m_items ;

const CItem * CContainer :: getItem(const CItemKey& rItemKey)const
{TItemKeysConstIterator it = m_items.find(rItemKey);

if(it!= m_items.end())
返回static_cast< const CItem *>(it-> getOwner());

返回(NULL);
}
============================================ ====== ====

我做错了什么?

我也尝试将m_items.find(rItemKey)修改为
m_items.find (& rItemKey),但这也没有帮助。
显然我在这里遇到了一个心理障碍。

有没有办法完成我想要的东西
实现(在一组中存储指针)?或者这是否根本不正确,因为定义必须包含键,而不是键的指针?
I never had any problems storing pointers in STL
containers such std::vector and std::map. The benefit
of storing pointers instead of the objects themselves
is mainly saving memory resources and performance (STL
containers hold *copies* of what''s passed to them via
the insert() method).

However, I am not sure how to accomplish that using
std::set. For various reasons, I cannot use vector or
map in my application. But I would like to use the
same optimization I have always used with STL
containers, which is letting them store pointers to
the items, not the items themselves.

In particular, the following code snippet compiles and
works beautifully (albeit no so efficient):

================ WORKING CODE SNIPPET ================
typedef std::set<CItemKey, std::less<CItemKey> > TItemKeys;
typedef TItemKeys::const_iterator TItemKeysConstIterator;
typedef TItemKeys::iterator TItemKeysIterator;

TItemKeys m_items;

const CItem* CContainer::getItem(const CItemKey& rItemKey) const
{
TItemKeysConstIterator it = m_items.find(rItemKey);

if (it != m_items.end())
return static_cast<const CItem*>(it->getOwner());
else
return (NULL);
}
================================================== ====
However, when I modify this to be pointer based
(notice the subtle difference), it does not even
compile! It fails on the find() statement for
inability to convert the type of the parameter (or the
return value):

================ WORKING CODE SNIPPET ================
typedef std::set<CItemKey*, std::less<CItemKey> > TItemKeys;
You are using a comparison function that produces a type mismatch. Either
use std::less<T*> or something like

pointee_comapare ( CItemKey const * a, CItemKey const b * b ) {
return (*a) < (*b);
}
typedef TItemKeys::const_iterator TItemKeysConstIterator;
typedef TItemKeys::iterator TItemKeysIterator;

TItemKeys m_items;

const CItem* CContainer::getItem(const CItemKey& rItemKey) const
{
TItemKeysConstIterator it = m_items.find(rItemKey);

if (it != m_items.end())
return static_cast<const CItem*>(it->getOwner());
else
return (NULL);
}
================================================== ====

What am I doing wrong?

I also tried modifying m_items.find(rItemKey) to
m_items.find(&rItemKey) but that doesn''t help either.
Obviously I ran into a mental block here.

Is there a way to accomplish what I am trying to
achieve (storing pointers in a set)? Or is this
fundamentally incorrect, as set by definition must
contain keys, not pointers to keys?




地图可以包含指针。但是,回想一下std :: map< T>使用

std :: less< T>保持条目排序以便快速检索。如果您使用

std :: map< T *>相反,默认使用的比较谓词将比较指针而不是指针。如果你只想使用指针来实现

效率,这将不是你想要的。相反,你需要提供你自己的比较函数而不是std :: less< T *>将

比较转发给指定者。

Best


Kai-Uwe Bux



A map can contain pointers. However, recall that a std::map<T> uses
std::less<T> to keep the entries sorted for fast retrieval. If you use
std::map<T*> instead, the comparison predicate used by default will compare
the pointers not the pointees. If you want to use the pointers just for
efficiency, this will not be what you want. Instead, you need to provide
your own comparison function instead of std::less<T*> that forwards the
comparison to the pointees.
Best

Kai-Uwe Bux


Victor Bazarov写道:
Victor Bazarov wrote:
你的意思是非工作代码SNIPPET吗?
是的。抱歉打字错误。第二个代码片段是不工作的

一个。


诀窍是你正在寻找''m_items'中的元素
_points_与''rItemKey'相同_value_,但''find''只对相同的_pointer_看起来是
。将它更改为

TItemKeysConstIterator it = m_items.find(& rItemKey);

应该帮助它编译,但我不认为它工作得很好,因为项目具有相同的地址。
Did you mean "NON-WORKING CODE SNIPPET"? Yes. Sorry for the typo. The second code snippet is the non-working
one.

The trick is that you''re looking for the element in ''m_items'' that
_points_ to the same _value_ as ''rItemKey'', but ''find'' only looks
for the same _pointer_. Changing it to

TItemKeysConstIterator it = m_items.find(&rItemKey);

should help it compile, but I don''t see it work very well because
the item you pass will very unlikely have the same address as any
item in the set.




你是对的,我知道甚至在更改。但是,由于我不是那么精通STL,我想首先让它编译并且

然后处理正确的comaprison功能。

现在我无法解读VC ++给我的神秘的编译错误消息




它说:

============ START QUOTE ================

''class std :: _ Tree< ;类CItemKey *,

类CItemKey *,

struct std :: set< class CItemKey *,

struct std :: less< class CItemKey *>,

class std :: allocator< class CItemKey *> > :: _ Kfn,

struct std :: less< class CItemKey *>,

class std :: allocator< class CItemKey *> > :: const_iterator __thiscall

std :: set< class CItemKey *,

struct std :: less< class CItemKey *>,

class std :: allocator< class CItemKey *> > :: find(class CItemKey * const&

)const'':

无法将参数1从''const class CItemKey *''转换为''class

CItemKey * const& ''


原因:无法从''const class CItemKey *''转换为''类

CItemKey * const''

转换失去限定符

============ END QUOTE ================

显然这里存在一个常量问题,但我不明白

,其中从''const CItemKey *''转换为''CItemKey * const''是

未经尝试。



You are right and I knew that even before the change. However, since I
am not that proficient in STL, I wanted first to make it compile and
then take care of correct comaprison function.

Right now I cannot decipher the cryptic compilaation error messages
that VC++ gives me.

It says:

============ START QUOTE ================
''class std::_Tree<class CItemKey *,
class CItemKey *,
struct std::set<class CItemKey *,
struct std::less<class CItemKey *>,
class std::allocator<class CItemKey *> >::_Kfn,
struct std::less<class CItemKey *>,
class std::allocator<class CItemKey *> >::const_iterator __thiscall
std::set<class CItemKey *,
struct std::less<class CItemKey *>,
class std::allocator<class CItemKey *> >::find(class CItemKey *const &
) const'' :
cannot convert parameter 1 from ''const class CItemKey *'' to ''class
CItemKey *const & ''

Reason: cannot convert from ''const class CItemKey *'' to ''class
CItemKey *const ''
Conversion loses qualifiers
============ END QUOTE ================

Obviously there is a constness problem here, but I don''t understand
where a conversion from ''const CItemKey *'' to ''CItemKey *const'' was
attempted.


这篇关于可以std :: set保持指针键而不是键本身吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆