传递嵌套 C++矢量作为内置样式多维数组
如果我在 C++ 中有一个向量,我知道我可以安全地将它作为数组传递(指向所包含类型的指针):
void some_function(size_t size, int array[])
{
// impl here...
}
// ...
std::vector<int> test;
some_function(test.size(), &test[0]);
使用嵌套向量执行此操作安全吗?
void some_function(size_t x, size_t y, size_t z, int* multi_dimensional_array)
{
// impl here...
}
// ...
std::vector<std::vector<std::vector<int> > > test;
// initialize with non-jagged dimensions, ensure they're not empty, then...
some_function(test.size(), test[0].size(), test[0][0].size(), &test[0][0][0]);
编辑:
如果不安全,有哪些替代方案,如果我可以更改 some_function
的签名,如果我不能?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
简短的回答是“不”。
这里的元素
std::vector; > > test;
不会在连续内存区域中被替换。Short answer is "no".
Elements here
std::vector<std::vector<std::vector<int> > > test;
are not replaced in contiguous memory area.您只能期望
multi_Dimension_array
指向大小为test[0][0].size() * sizeof(int)
的连续内存块。但这可能不是您想要的。You can only expect
multi_dimensional_array
to point to a contiguos memory block of sizetest[0][0].size() * sizeof(int)
. But that is probably not what you want.获取向量中任何位置的地址并传递它是错误的。它可能看起来有效,但不要指望它。
原因与向量是向量而不是数组的原因密切相关。与数组不同,我们希望向量能够动态增长。我们希望对向量的插入是一个恒定的成本,而不是依赖于向量的大小,就像数组一样,直到达到分配的数组大小。
那么魔法是如何发挥作用的呢?当没有更多的内部空间来向向量添加下一个元素时,将分配一个两倍于旧空间大小的新空间。旧空间被复制到新空间,旧空间不再需要或不再有效,这使得指向旧空间的任何指针悬空。分配了两倍的空间,因此插入向量的平均成本是恒定的。
It is erroneous to take the address of any location in a vector and pass it. It might seem to work, but don't count on it.
The reason why is closely tied to why a vector is a vector, and not an array. We want a vector to grow dynamically, unlike an array. We want insertions into a vector be a constant cost and not depend on the size of the vector, like an array until you hit the allocated size of the array.
So how does the magic work? When there is no more internal space to add a next element to the vector, a new space is allocated twice the size of the old. The old space is copied to the new and the old space is no longer needed, or valid, which makes dangling any pointer to the old space. Twice the space is allocated so the average cost of insertion to the vector that is constant.
是的,如果您只想访问最内部向量,并且只要您知道它包含的元素数量,并且您不会尝试访问更多元素。
但是看到你的函数签名,你似乎想要访问所有三个维度,在这种情况下,不,这是无效的。
另一种方法是,您可以为每个最内部向量调用函数
some_function(size_t size, int array[])
(如果这可以解决您的问题);为此你可以做这个技巧(或类似的东西):Yes, IF you want to access the inner-most vector only, and as long you know the number of elements it contains, and you don't try accessing more than that.
But seeing your function signature, it seems that you want to acess all three dimensions, in that case, no, that isn't valid.
The alternative is that you can call the function
some_function(size_t size, int array[])
for each inner-most vector (if that solves your problem); and for that you can do this trick (or something similar):一种非常简单的解决方案是将嵌套向量的内容简单地复制到一个向量中并将其传递给该函数。但这取决于您愿意承担多少开销。
可悲的是:嵌套向量不是一个好的做法。将所有内容存储在连续内存中并管理访问的矩阵类确实更高效且不那么难看,并且可能允许类似 T*matrix::get_raw() 的内容,但内容的排序仍然是一个实现细节。
A very simple solution would be to simply copy the contents of the nested vector into one vector and pass it to that function. But this depends on how much overhead you are willing to take.
That being sad: Nested vectorS aren't good practice. A matrix class storing everything in contiguous memory and managing access is really more efficient and less ugly and would possibly allow something like
T* matrix::get_raw()
but the ordering of the contents would still be an implementation detail.简单的回答——不,不是。你尝试编译这个吗?为什么不直接传递整个 3D 矢量作为参考呢?如果您尝试以这种方式访问旧的 C 代码,则不能。
Simple answer - no, it is not. Did you try compiling this? And why not just pass the whole 3D vector as a reference? If you are trying to access old C code in this manner, then you cannot.
传递向量或对其的引用会更安全:
然后您可以获取函数内的大小和项目,从而减少出错的风险。您可以复制向量或传递指针/引用,具体取决于预期的大小和用途。
如果需要跨模块传递,那么就变得稍微复杂一些。
It would be much safer to pass the vector, or a reference to it:
You can then get the size and items within the function, leaving less risk for mistakes. You can copy the vector or pass a pointer/reference, depending on expected size and use.
If you need to pass across modules, then it becomes slightly more complicated.
尝试使用
&top_level_vector[0]
并将其传递给需要int*
的 C 风格函数是不安全的。为了支持对多维数组的正确 C 风格访问,所有数组层次结构的所有字节都必须是连续的。在 c++
std::vector
中,这对于向量包含的项是正确的,但对于向量本身则不然。如果您尝试获取顶级向量的地址,ala&top_level_vector[0]
,您将得到一个向量数组,而不是一个int
数组代码>.向量结构不仅仅是所包含类型的数组。它被实现为一个包含指针以及大小和容量簿记数据的结构。因此,问题的
std::vector > >
或多或少是一个结构的层次树,用指针缝合在一起。只有该树中的最终叶节点是连续int
值块。并且每个内存块不一定与任何其他块相邻。为了与 C 接口,您只能传递单个
向量
的内容。因此,您必须创建一个大小为x * y * z
的std::vector
。或者,您可以决定重新构造 C 代码,以一次处理单个一维数据条带。然后你可以保留层次结构,只传递叶向量的内容。Trying to use
&top_level_vector[0]
and pass that to a C-style function that expects anint*
isn't safe.To support correct C-style access to a multi-dimensional array, all the bytes of all the hierarchy of arrays would have to be contiguous. In a c++
std::vector
, this is true for the items contained by a vector, but not for the vector itself. If you try to take the address of the top-level vector, ala&top_level_vector[0]
, you're going to get an array of vectors, not an array ofint
.The vector structure isn't simply an array of the contained type. It is implemented as a structure containing a pointer, as well as size and capacity book-keeping data. Therefore the question's
std::vector<std::vector<std::vector<int> > >
is more or less a hierarchical tree of structures, stitched together with pointers. Only the final leaf nodes in that tree are blocks of contiguousint
values. And each of those blocks of memory are not necessarily contiguous to any other block.In order to interface with C, you can only pass the contents of a single
vector
. So you'll have to create a singlestd::vector<int>
of sizex * y * z
. Or you could decide to re-structure your C code to handle a single 1-dimensional stripe of data at a time. Then you could keep the hierarchy, and only pass in the contents of leaf vectors.