2

我在一个列表中有很多数据,比如每个元素有几个 kbytes,我想逐个提取每个元素来进行一些数值处理。这些数据最初存储为 float[]。由于处理涉及大量索引和全局计算,我认为 valarray 可能易于编程。但是如果我使用 valarray,我可能必须先从数组复制到 valarray,然后再复制回数组。有没有办法避免这种情况?有什么方法可以让我直接在数组上工作吗?或者你有更好的方法来解决类似的问题吗?

4

2 回答 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 回答