用 std::valarray 替换 POD C 样式数组是个坏主意吗?
Is it a bad idea to replace POD C-style array with std::valarray?
我正在使用一个写得不好且有很多内存泄漏的代码库。
它使用了很多包含原始指针的结构,这些原始指针主要用作动态数组。
尽管结构通常在函数之间传递,但这些指针的分配和释放放置在随机位置,不容易跟踪/推理/理解。
我将其中一些更改为类,并将这些指针更改为类本身。它们运行良好,看起来不是很丑陋,除了我禁止这些类的复制构造和复制分配,仅仅是因为我不想花时间实现它们。
现在我在想,我是在重新发明轮子吗?为什么我不用 std:array 或 std::valarray 替换 C 样式数组?
我更喜欢std::valarray,因为它使用堆内存和RAIIed。std::array 在我的开发环境中(尚)不可用。
编辑1:std::array的另一个优点是,这些动态数组中的大多数都是POD(主要是int16_t,int32_t和float)数组,数字API可以使生活更轻松。
在开始之前,我需要注意什么吗?
我能想到的一个是,可能没有一种简单的方法可以将 std::valarray 或 std::array 转换回 C 风格的数组,并且我们的部分代码确实使用指针算法,并且需要将数据呈现为普通的 C 样式数组。
别的东西?
编辑 2
我最近遇到了这个问题。关于std::valarray
的一个非常糟糕的事情是,直到 C++11 才能安全地进行复制分配。
正如该答案中引用的那样,在 C++03 及更早版本中,如果源和目标的大小不同,则为 UB。
C 样式数组的标准替换将是 std::vector
。 std::valarray
是一些"奇怪"的数学向量,用于做类似数字计算的事情。它并不是真正设计用于存储任意对象的数组。
话虽如此,使用 std::vector
很可能是一个非常好的主意。它会修复您的泄漏,使用堆,可调整大小,具有出色的异常安全性等等。
它还保证数据存储在一个连续的内存块中。您可以使用 data()
成员函数获取指向所述块的指针,或者,如果您是 C++11 之前,则可以使用 &v[0]
表示非空向量v
。然后,您可以像往常一样使用它进行指针业务。
std::unique_ptr<int[]>
接近于拥有int*
的直接替代品。 它有一个很好的属性,它不会隐式复制自己,但它会隐式移动。
复制的操作将生成编译时错误,而不是运行时效率低下。
除了销毁时的空检查外,它对该拥有int*
几乎没有运行时开销。 它使用的空间不超过int*
。
std::vector<int>
存储 3 个指针和隐式副本(这可能很昂贵,并且与现有代码行为不匹配)。
我会从std::unique_ptr<int[]>
开始作为第一遍并让它工作。 在我确定智能缓冲区管理值得之后,我可能会将一些代码转换为std::vector<int>
。
实际上,作为第一遍,我会寻找memcpy
和memset
以及类似的功能,并确保它们在开始添加 RAII 成员之前不会在有问题的结构上运行。
std::unique_ptr<int[]>
意味着为结构创建的默认析构函数将为您执行 RAII 清理,而无需编写任何新代码。
我更喜欢std::vector
作为c样式数组的替代品。您可以通过以下.data()
直接访问基础数据(类似于裸指针):
返回指向用作元素存储的基础数组的指针。