【问题标题】:Get pointer to raw data in set like &(vector[0])获取指向集合中原始数据的指针,例如 &(vector[0])
【发布时间】:2013-01-24 02:24:13
【问题描述】:

要获得指向向量中数据的指针,我们可以使用

vector<double> Vec;    
double* Array_Pointer = &(Vec[0]);
Function(Array_Pointer);

是否有可能获得指向 set 中数据的指针?我可以像上面那样将它用作数组指针吗?


如果不可能,使向量脱离集合的最佳方法是什么?我的意思是没有循环遍历所有元素。

【问题讨论】:

  • 在向量中,该数据是连续的。这将如何在一组中发挥作用?
  • 数据容器在集合中也应该是连续的!为什么不?我指的不是元素的顺序,而是元素的存储。否则效率不高
  • 不太可能。标准不能保证它是连续的,并且使其连续可能会破坏一些复杂性要求。
  • 因为 set 的保证之一是插入、擦除和搜索操作都有 O(log(n)) 的复杂度。如果数据是连续的,就很难兑现承诺。
  • 您也许可以使用std::priority_queue 而不是std::set;这个结构可能有连续的存储,并且是部分排序的,但不是完全排序的。

标签: c++ pointers vector set containers


【解决方案1】:

不,这不一定是可能的。 C++ ISO 标准明确保证std::vector 中元素的连续存储,因此您可以安全地获取第一个元素的地址,然后像指向原始数组一样使用该指针。标准库中的其他容器没有这个保证。

这样做的原因是为了有效地支持std::set 上的大多数操作,实现需要使用平衡二叉搜索树等复杂的数据结构来存储和组织数据。这些结构本质上是非线性的,需要将节点分配并链接在一起。在标准规定的时间限制(大多数操作的摊销 O(log n))内,有效地让它与平面数组中的元素一起工作将是困难的,如果不是不可能的话。

编辑:针对您的问题 - 如果没有一些代码在某处迭代集合并复制元素,就无法从 std::set 构建 std::vector。您可以通过使用std::vector range 构造函数来执行此操作,而无需自己显式使用任何循环:

std::vector<T> vec(mySet.begin(), mySet.end());

希望这会有所帮助!

【讨论】:

  • 谢谢,使向量脱离集合的最佳方法是什么?
  • 它是否也适用于地图:vec(myMap.begin(), myMap.end()); ?
  • @Hesam- 由于地图存储键/值对,这仅在向量存储键/值对时才有效。没有直接的方法可以通过这种方式获取键或值;您需要使用显式循环。
  • @chris- 是的,但是您需要定义一个函数(或 lambda)来仅获取该对的第一个或第二个元素。也许我最初的主张太强了。
  • @templatetypedef,好吧,这不是那么麻烦:p [](decltype(myMap)::value_type &amp;p) {return p.first;}
【解决方案2】:

没有。无法以您可以执行此操作的方式实现 set

如果您以将元素存储在单个数组中的方式实现set,那么当您添加更多元素时,该数组将不可避免地需要在某个时候重新分配。届时,对现有元素的任何引用都将失效。

set 的一个特点是它保证如果您添加(或删除)其他元素,对元素的引用将永远不会失效。如 [associative.reqmts] 中所述:

insertemplace 成员不应影响迭代器和对容器的引用的有效性,erase 成员应仅使迭代器和对已擦除元素的引用无效。

因此不可能以这样一种方式实现set,将集合的所有元素都存储在一个数组中。

请注意,这与效率要求无关,例如 O(log n) 插入/删除/查找(如果您非常努力地眯着眼睛并至少允许摊销 O(log n) 插入时间),或维护排序顺序,或类似的东西。如果只是这些,则可以使用底层元素之上的数据结构轻松处理它们,并且元素本身可以存储在数组中。它甚至与 iterator 失效的保证没有任何关系,因为迭代器是抽象的。

不,唯一阻碍你的是参考失效要求。

【讨论】:

    猜你喜欢
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 2014-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-08
    • 2016-08-01
    相关资源
    最近更新 更多