2011-07-27 113 views
2

我在列表中有很多数据,比如说每个元素有几个字节,我想每个数据都要进行一些数字处理。这些数据最初存储为float []。由于处理涉及很多索引和全局计算,我认为valarray可能很容易编程。但是,如果我使用valarray,我可能不得不首先从数组复制到valarray,然后将其复制回数组。有什么办法可以避免这种情况?任何方式让我直接在数组上工作?或者你有更好的方法来解决类似的问题?有没有办法避免valarray和数组之间的复制?

+1

你试图解决的实际问题是什么? –

+0

@tomalak:只想处理内部存储在列表中的大量数据。列表中的每个元素都是数据结构或类。处理过程主要涉及数据结构中数组中所有或某些值的数值计算。希望我这次明确。 – shangping

+0

我完全不理解这个问题。也许我只是很厚。 –

回答

1

valarray类型没有提供任何方式将现有数组用于其数据存储;它总是为自己制作一个副本。不要将数据存储在普通数组中,而应将数值从一开始直接存储在valarray中。调用v.resize来设置大小,并使用[]运算符为其分配值,或使用&v[0]获取指向第一个值的指针,并像迭代器或缓冲区指针那样使用它 - 将valarray的元素连续存储在内存中。

+0

谢谢,我明白你的意思。问题是我无法改变之前涉及太多变化的阵列设计。 – shangping

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布局可以在编译的另一种模式是不同的(模式的例子:调试/释放;不同的平台,不同版本的标准库)
  • 如果你的计算调整valarray将以任何方式尝试重新分配缓冲区并崩溃
  • 如果valarray的实现假定其缓冲区具有例如16字节对齐,它可能会崩溃,做计算错误或只是工作缓慢(根据您的平台)
  • (我相信有一些原因吧不工作)

不管怎么说,这是描述作为标准的“未定义行为”,严格来说,如果您使用此解决方案,可能会发生任何事情。

相关问题