C++ 大向量搜索项
Posted
技术标签:
【中文标题】C++ 大向量搜索项【英文标题】:C++ Big vector search item 【发布时间】:2012-11-17 19:38:39 【问题描述】:第一次在这里发帖,这让我发疯了!我解释的不是很清楚,所以我试着举个例子。
我正在尝试检索一个非常大 (100k) 向量中的元素以将其擦除。迭代槽需要很长时间......所以我尝试了这个:
这是我列表中的一个小例子。它存储在我的单例粒子发射器类中。
vector<Particle> particles;
particles.reserve(100);
这是我的粒子的精简版
class Particle
Particle:
~Particle:
void Delete
int listNum = (this - &particles[0]);
particles.erase(particles.begin+listNum);
;
这一切都很好,但我不想将每个粒子都保存在堆栈中,所以我想更改它
vector<Particle> particles;
进入
vector<Particle*> particles;
现在我的问题是:如果向量由粒子指针组成,是否仍然可以从列表中删除和擦除粒子?
我不确定我是否清楚我的问题,但我希望你能理解!
或者,如果有人知道更好的性能明智的解决方案,我想听听!
提前致谢!
【问题讨论】:
你的Particle
类不应该知道是什么容器保存它。
粒子有多大?如果复制构造很昂贵,那么您应该存储为指针,但使用指针容器(例如boost::ptr_vector
),我同意克里斯,将容器知识灌输到类不是一个好主意......
另外,为了减少搜索时间,你可以有一个排序的向量吗?
“但我不想将每个粒子都保存在堆栈中”std::vector
的存储在堆上。
@chris:一般来说建议不错,但有时出于性能原因,您需要偏离最佳实践。
【参考方案1】:
你打算如何使用这个std::vector
?
您说迭代需要很长时间,但如果您的目标是迭代所有值,那么您根本无法比连续数组做得更好。您谈到从容器中删除元素,这表明您需要一个动态数组,这正是std::vector
的含义。
无论如何,您绝对不想存储原始指针向量。如果您测量并发现由于使用某些操作而导致性能不足,您的两个选项应该是 std::vector<Particle>
(通常首选)或 std::vector<unique_ptr<Particle>>
(仅限 C++11)。根据您的用例,std::map<Particle>
或 std::set<Particle>
可能是个好主意,但我们没有足够的信息。
您没有在堆栈上存储任何Particle
。 std::vector
中的每个元素都已经在空闲存储区(“堆”)中。
您的插入和删除代码也应该与您的Particle
类无关。插入和删除是对容器的操作,而不是对包含的元素的操作。
要回答您的问题,我们需要了解一些事情。
首先,Particle
有多大?这可能是最重要的信息。
其次,你用容器做什么?您通常是在查看每个 Particle
并与它们一起做事,还是在整个容器中搜索特定的 Particle
?如果您正在搜索,您是否尝试根据某种键进行查找(例如,每个 Particle
都有一个唯一 ID,并且您在该 ID 上查找整个 Particle
),或者您正在查找如果一个Particle
匹配另一个(也就是说,您根据Particle
的身份进行查找)?
如果您正在查找个人Particle
,那么std::set
应该是您使用方便的首选,因为它允许进行二分搜索。如果您的用例让您按键搜索粒子,那么您需要std::map<Key, Particle>
。
如果你有一堆粒子,并且你想从容器中删除一些,那么对象的大小就很重要了。但是,在这种情况下,您通常需要std::vector
。
简而言之,我需要更多信息才能完整回答您的问题。
【讨论】:
好的,谢谢你的信息,我会先处理你的建议,看看我能不能从中做点什么!【参考方案2】:如果您担心将向量放入堆栈,为什么不尝试这样的事情:
vector <Particle> * particles = new vector <Particle>;
这将使向量持续到您delete
它。此外,如果您担心性能问题,set
将是一个好主意。这保证了所有插入和删除都是对数时间,并且您不必使用自己的删除函数。要在 C++11 中获得更好的性能,请尝试 unordered_set
。
【讨论】:
std::vector
已经在堆上分配。你的改变并没有真正完成任何事情。
刚刚意识到这一点。然而,由于他似乎是在一个函数中声明它,所以如果有必要,只要他需要,执行 new/delete
方法将保留它。
根据需要保留它无论如何都应该有效,特别是对于 C++11 移动语义。此外,OP 显然将其声明为 globally,这很可怕,但绝对不需要复制/移动。
哈哈,不是全局的,但我把它放在我的粒子发射器类中
存储指向 std::vector 而不是 std::vector 本身的指针并没有真正的优势。 std::vector 通常在堆栈上分配 sizeof(pointer) * 3
,而不管 std::vector 中包含多少元素。以上是关于C++ 大向量搜索项的主要内容,如果未能解决你的问题,请参考以下文章