我在一个列表中有很多数据,比如每个元素有几个 kbytes,我想逐个提取每个元素来进行一些数值处理。这些数据最初存储为 float[]。由于处理涉及大量索引和全局计算,我认为 valarray 可能易于编程。但是如果我使用 valarray,我可能必须先从数组复制到 valarray,然后再复制回数组。有没有办法避免这种情况?有什么方法可以让我直接在数组上工作吗?或者你有更好的方法来解决类似的问题吗?
问问题
1156 次
2 回答
1
该valarray
类型不提供任何方式来使用现有数组作为其数据存储;它总是为自己制作副本。不要将数据存储在普通数组中,而是valarray
从一开始就直接将值存储在。调用v.resize
以设置大小,并使用运算符为其赋值[]
,或者使用&v[0]
获取指向第一个值的指针并像使用迭代器或缓冲区指针一样使用它—— a 的元素valarray
连续存储在内存中。
于 2011-07-27T17:32:56.360 回答
1
警告:丑陋的黑客。
在我的系统(MS Visual Studio)上,valarray
该类的定义如下:
template<class _Ty>
class valarray
{
...
private:
_Ty *_Myptr; // current storage reserved for array
size_t _Mysize; // current length of sequence
size_t _Myres; // length of array
};
所以我可以构建自己的具有相同布局的类(具有良好的信心):
struct my_valarray_hack
{
void *_Myptr;
size_t num_of_elements;
size_t size_of_buffer;
};
然后创建一个空valarray
并覆盖其内部变量,使其指向您的数据。
void do_stuff(float my_data[], size_t size)
{
valarray<float> my_valarray;
my_valarray_hack hack = {my_data, size, size};
my_valarray_hack cleanup;
assert(sizeof(my_valarray) == sizeof(hack));
// Save the contents of the object that we are fiddling with
memcpy(&cleanup, &my_valarray, sizeof(cleanup));
// Overwrite the object so it points to our array
memcpy(&my_valarray, &hack, sizeof(hack));
// Do calculations
...
// Do cleanup (otherwise, it will crash)
memcpy(&my_valarray, &cleanup, sizeof(cleanup));
// Destructor is silently invoked here
}
这不是推荐的做事方式;仅当您没有其他方法可以实现您想要的东西时才应该考虑它(甚至那时也可能没有)。可能失败的可能原因:
- 在另一种编译模式下的布局
valarray
可能会有所不同(模式示例:debug/release;不同平台;不同版本的标准库) - 如果您的计算
valarray
以任何方式调整大小,它将尝试重新分配您的缓冲区并崩溃 - 如果实现
valarray
假设其缓冲区具有例如 16 字节对齐,它可能会崩溃、执行错误计算或工作缓慢(取决于您的平台) - (我相信还有其他一些原因使它不起作用)
无论如何,它被标准描述为“未定义的行为”,所以严格来说,如果你使用这个解决方案,任何事情都可能发生。
于 2013-05-08T18:11:48.607 回答