C++ 我应该返回一个迭代器还是一个指向STL容器中元素的指针?

C++ 我应该返回一个迭代器还是一个指向STL容器中元素的指针?,c++,stl,C++,Stl,我正在开发一个将现有代码移植到不同平台的引擎。现有代码是使用第三方API开发的,我的引擎将根据我的新平台重新定义这些第三方API函数 以下定义来自API: typedef unsigned long shape_handle; shape_handle make_new_shape( int type ); 我需要重新定义make_new_shape,我可以选择重新定义shape_handle 我已定义此结构(简化): make\u new\u shape的调用者并不关心shape的底

我正在开发一个将现有代码移植到不同平台的引擎。现有代码是使用第三方API开发的,我的引擎将根据我的新平台重新定义这些第三方API函数

以下定义来自API:

typedef unsigned long shape_handle;    
shape_handle make_new_shape( int type );
我需要重新定义
make_new_shape
,我可以选择重新定义
shape_handle

我已定义此结构(简化):

make\u new\u shape
的调用者并不关心
shape
的底层结构,它只需要一个“句柄”,以便调用如下函数:

void `set_shape_color( myshape, RED );`
其中,
myshape
是形状的控制柄

我的引擎将管理
形状
对象的内存,其他要求规定引擎应将
形状
对象存储在列表或其他可编辑容器中


我的问题是,表示这个句柄最安全的方法是什么?如果
形状本身将存储在std::list中,那么迭代器、指针、索引?

如果在对象被删除后试图访问迭代器或指针,那么迭代器或指针都会做坏事,因此两者本质上都不安全。迭代器的优点是可以用来访问集合的其他成员

因此,如果您只想访问您的形状,那么指针将是最简单的。如果您想遍历列表,那么使用迭代器


索引在列表中是无用的,因为std::list不会重载[]运算符

ii如果内部表示是一个形状列表,那么指针和迭代器是安全的。一旦分配了一个元素,就不会发生重新定位。出于明显的访问性能原因,我不推荐索引。O(n)在列表的情况下

如果您使用的是向量,那么就不要使用迭代器或指针,因为当您超过向量容量时,元素可能会重新定位,并且您的指针/迭代器将变得无效


如果您想要一个安全的表示,而不考虑内部容器,则创建指向形状的指针的容器(列表/向量),并将形状指针返回给客户端。即使容器在内存中移动,形状对象也将保持在相同的位置。

答案取决于您的表示:

  • 对于
    std::list
    ,请使用
    迭代器(而不是指针),因为
    迭代器可以在不遍历整个列表的情况下删除元素
  • 对于
    std::map
    boost::unordered\u map
    ,使用
    键(当然)
如果使用关联容器,您的设计将非常强大,因为关联容器使您能够查询对象的存在,而不是调用未定义的行为


试着对
map
unordered\u map
进行基准测试,看看哪一个更快:)

迭代器并不比指针更安全,但是如果您使用的是检查过的STL实现,它们比原始指针有更好的诊断功能

例如,在调试生成中,如果返回指向列表元素的指针,然后删除该列表元素,则会有一个悬空指针。如果你访问它,你会崩溃,你能看到的只是垃圾数据。这会使我们很难找出哪里出了问题

如果您使用迭代器,并且您有一个已检查的STL实现,那么一旦您访问迭代器到一个已擦除的元素,就会得到一条类似“迭代器已失效”的消息。那是因为你删除了它指向的元素。砰的一声,你节省了大量的调试工作


所以,不是O(n)性能的指标。在指针和迭代器之间-始终是迭代器

为什么选择std::list?@jk-我需要能够在容器中间添加和删除
Shape
对象。你肯定不想重新定义Shape\u句柄(或创建新的形状)。@Martin,我不同意。我真的很想重新定义
使你成为一个新的形状
:-)你就是这么想的。试试看,我相信你会发现你没有,但你要花十年的时间才能意识到你的错误。+1:你是否提供对内部表示(迭代器)的访问(指针)是最重要的区别。
void `set_shape_color( myshape, RED );`