【发布时间】:2019-03-10 09:10:10
【问题描述】:
如果问题不是很详细,请提前抱歉,但这是一个非常具体的案例。
我想在一个非常像双端队列的容器中添加元素:我希望能够以有效的方式 push_back 和 pop_front。问题是,该容器将用于存储 SFML 库中的 sf::Vertex,因此要渲染它,我必须执行以下操作:
window.draw(&container[0], container.size(), sf::LineStrip)
这不适用于双端队列,因为双端队列的元素不是连续存储的。所以,由于我对内存使用了解不多,我正在考虑两种选择:
1) 使用双端队列并在渲染时复制向量中的元素:
std::deque<sf::Vertex> container;
...
std::vector<sf::Vertex> buffer {container.front(), container.back()};
window.draw(&buffer[0], buffer.size(), sf::LineStrip};
2) 直接使用vector存储元素,并调用vec.erase(vec.begin());弹出第一个位置的元素
由于几乎每一帧都会调用 pop_front,我想知道哪种方法在内存方面的成本最低?
如果你有任何其他想法,我会接受它们:)
编辑:
所以这是我昨天晚上实现的:
https://github.com/grybouilli/SFML-sf-Vertex-FIFO-like-container src 和 hdr 文件中的主要代码:)
【问题讨论】:
-
当您要求内存消耗效率时,
vec.erase(vec.begin());不适合向量大小 IIRC。我不确定std::deque是否旨在更好地做到这一点。至少std::vector公开了一个函数shrink_to_fit(),它似乎承诺释放一些以前分配的内存。我不确定这是正确的操作(性能方面),应该在几乎每个渲染帧中调用。 -
我可能会使用一个环形缓冲区,如果需要的话,调用 draw() 两次。但我也会尝试其他方法并衡量它们的性能。
-
顶点的顺序重要吗?另外,立即释放内存有多重要? push/pop 的速度不是更重要吗?
-
我要收集有关环形缓冲区的信息,这听起来是个好主意!是的,顶点的顺序很重要,因为在渲染它们时,我想将每个顶点与 Line 连接起来,我可以通过提供 sf::LineStrip 作为绘图调用的参数来做到这一点。由于我还要推送很多顶点,其中一些在某些时候甚至不会出现在屏幕上,而那些是我想要擦除的那些
标签: c++ vector sfml deque memory-efficient