将动态数组包装到 STL/Boost 容器中?
我需要将动态分配的数组(例如从 a = new double[100] )包装到 std::vector (最好)而不复制数组。 此限制是由于我想要包装的数组是从文件映射而来的,因此仅执行向量(a,a+size)就会使内存使用量增加一倍。
有什么技巧可以做到这一点吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
最好的解决方案之一是类似于 STLSoft 的 array_proxy 模板。不幸的是,doxygen 从源代码生成的文档页面并不能帮助理解模板。源代码实际上可能更好一点:
http://www. stlsoft.org/doc-1.9/array__proxy_8hpp-source.html
array_proxy<>
模板在 Matthew Wilson 的书《不完美的 C++》。我使用的版本是 STLSoft 网站上内容的精简版本,因此我不必引入整个库。我的版本不是那么可移植,但这使得它比 STLSoft 上的版本简单得多(它跳过了很多可移植性的障碍)。如果您像这样设置变量:
变量
myArrayProx
有许多 STL 接口 -begin()
、end()
、size()
、迭代器等。因此,在很多方面,
array_proxy
对象的行为就像一个向量(尽管push_back()
不是t 在那里,因为 array_proxy<> 无法增长 - 它不管理数组的内存,它只是将其包装在更接近向量的东西中)。array_proxy<> 的一件非常好的事情是,如果将它们用作函数参数类型,则函数可以确定传入数组的大小,而本机数组则不然。并且包装数组的大小不是模板类型的一部分,因此使用起来非常灵活。
One of the best solutions for this is something like STLSoft's array_proxy<> template. Unfortunately, the doc page generated from the source code by doxygen isn't a whole lot of help understanding the template. The source code might actually be a bit better:
http://www.stlsoft.org/doc-1.9/array__proxy_8hpp-source.html
The
array_proxy<>
template is described nicely in Matthew Wilson's book, Imperfect C++. The version I've used is a cut-down version of what's on the STLSoft site so I didn't have to pull in the whole library. My version's not as portable, but that makes it much simpler than what's on STLSoft (which jumps through a whole lot of portability hoops).If you set up a variable like so:
The variable
myArrayProx
has many of the STL interfaces -begin()
,end()
,size()
, iterators, etc.So in many ways, the
array_proxy<>
object behaves just like a vector (thoughpush_back()
isn't there since thearray_proxy<>
can't grow - it doesn't manage the array's memory, it just wraps it in something a little closer to a vector).One really nice thing with
array_proxy<>
is that if you use them as function parameter types, the function can determine the size of the array passed in, which isn't true of native arrays. And the size of the wrapped array isn't part of the template's type, so it's quite flexible to use.boost::iterator_range 提供了类似容器的接口:
A boost::iterator_range provides a container-like interface:
我曾经决心完成同样的事情。经过几天的思考和尝试,我认为这不值得。我最终创建了自己的自定义向量,其行为类似于 std::vector,但只具有我实际需要的功能,例如边界检查、迭代器等。
如果您仍然希望使用 std::vector,这是我当时能想到的唯一方法是创建一个自定义分配器。我从来没有写过,但鉴于这是控制 STL 内存管理的唯一方法,也许可以在那里做一些事情。
I was once determined to accomplish the exact same thing. After a few days of thinking and trying I decided it wasn't worth it. I ended up creating my own custom vector that behaved like std::vector's but only had the functionality I actually needed like bound checking, iterators etc.
If you still desire to use std::vector, the only way I could think of back then was to create a custom allocator. I've never written one but seeing as this is the only way to control STL's memory management maybe there is something that can be done there.
不,使用
std::vector
是不可能的。但如果可能的话,您可以创建具有此大小的向量,并可能将文件映射到该向量。
No, that is not possible using a
std::vector
.But if possible you can create the vector with this size, and possible map the file to that instead.
指向映射区域元素的指针向量怎么样(由于 sizeof(double*) < sizeof(double) 减少了内存消耗)?这对你来说可以吗?
有一些缺点(主要是您需要特殊的谓词进行排序),但也有一些好处,例如,您可以删除元素而不更改实际映射内容(或者拥有偶数个具有不同元素顺序的此类数组,而不需要更改实际映射内容)值)。
在映射文件上使用 std::vector 的所有解决方案都有一个共同的问题:将矢量内容“钉”到映射区域。这是无法跟踪的,您只能自己注意不要使用可能导致矢量内容重新分配的东西。所以无论如何都要小心。
What about vector of pointers that point to your mapped area elements (reduced memory consumption as sizeof(double*) < sizeof(double))? Is this OK for you?
There is some drawbacks (primary is you need special predicates for sort) but some benefits too as you can, for example, delete elements without changing actual mapped content (or have even number of such arrays with different order of elements without any change to actual values).
There is common problem of all the solutions with std::vector on mapped file: to 'nail' vector content to mapped area. This can't be tracked, you can only watch after yourself to not use something which could lead to vector content re-allocation. So be careful in any case.
您可以使用 array_proxy<>,或者查看 Boost.Array。它为您提供 size()、front()、back()、at()、operator[] 等。就个人而言,我更喜欢 Boost.Array,因为无论如何 Boost 更流行。
You could go with array_proxy<>, or take a look at Boost.Array . It gives you size(), front(), back(), at(), operator[], etc. Personally, I'd prefer Boost.Array since Boost is more prevalent anyway.
好吧,向量模板允许提供您自己的内存分配器。我自己从来没有这样做过,但我想让它指向你的数组并不难,也许通过放置新运算符......只是一个猜测,如果我尝试并成功,我会写更多。
well, the vector template allows to provide your own memory allocator. I never did it myself but I guess it is not that difficult to get it to point to your array, maybe with placement new operator... just a guess, I write more if I try and succeed.
这是您问题的解决方案。在我想出一个可行的解决方案之前,我断断续续地尝试了很长一段时间。需要注意的是,使用后必须将指针清零,以避免双重释放内存。
或者,您可以创建一个继承自 Vector 的类,并在销毁时清空指针:
Here's the solution to your question. I had been attempting this off and on for quite some time before I came up with a workable solution. The caveat is that you have got to zero out the pointers after use in order to avoid double-freeing the memory.
Alternatively you could just make a class that inherits from vector and nulls out the pointers upon destruction: