用 std::valarray 替换 POD C 样式数组是个坏主意吗?

Is it a bad idea to replace POD C-style array with std::valarray?

本文关键字:样式 valarray std 替换 POD 数组      更新时间:2023-10-16

我正在使用一个写得不好且有很多内存泄漏的代码库。

它使用了很多包含原始指针的结构,这些原始指针主要用作动态数组。

尽管结构通常在函数之间传递,但这些指针的分配和释放放置在随机位置,不容易跟踪/推理/理解。

我将其中一些更改为类,并将这些指针更改为类本身。它们运行良好,看起来不是很丑陋,除了我禁止这些类的复制构造和复制分配,仅仅是因为我不想花时间实现它们。

现在我在想,我是在重新发明轮子吗?为什么我不用 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::vectorstd::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>

实际上,作为第一遍,我会寻找memcpymemset以及类似的功能,并确保它们在开始添加 RAII 成员之前不会在有问题的结构上运行。

std::unique_ptr<int[]>意味着为结构创建的默认析构函数将为您执行 RAII 清理,而无需编写任何新代码。

我更喜欢std::vector作为c样式数组的替代品。您可以通过以下.data()直接访问基础数据(类似于裸指针):

返回指向用作元素存储的基础数组的指针。