用 std::valarray 替换 POD C 样式数组是个坏主意吗?
Is it a bad idea to replace POD C-style array with std::valarray?
我正在使用一个代码库,该代码库编写得很糟糕并且存在大量内存泄漏。
它使用了很多包含原始指针的结构,这些结构主要用作动态数组。
虽然结构经常在函数之间传递,但这些指针的分配和释放是随机放置的,不容易tracked/reasoned/understood。
我将它们中的一些更改为 类 并且那些指针将由 类 自己 RAIIed。它们工作得很好,看起来也不是很丑,除了我禁止复制构造和复制赋值那些 类 只是因为我不想花时间实现它们。
现在想想,我是不是在重新发明轮子?为什么不用 std:array 或 std::valarray 替换 C 风格的数组?
我更喜欢 std::valarray 因为它使用堆内存和 RAIIed。 std::array 在我的开发环境中(还)不可用。
Edit1: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
是一些 "weird" 数学向量,用于进行类似数字计算的事情。它并不是真正设计用于存储任意对象的数组。
也就是说,使用 std::vector
很可能是一个 非常 的好主意。它将修复您的泄漏、使用堆、可调整大小、具有出色的异常安全性等等。
它还保证数据存储在一个连续的内存块中。您可以使用 data()
成员函数获取指向所述块的指针,或者,如果您是 C++11 之前的版本,则使用 &v[0]
获取非空向量 v
。然后您可以像往常一样使用它处理指针业务。
我更喜欢std::vector
as the replacement of c-style arrays. You can have a direct access to the underlying data (something like bare pointers) via .data()
:
Returns pointer to the underlying array serving as element storage.
std::unique_ptr<int[]>
接近拥有 int*
的替代品。它有一个很好的 属性,它将 不会 隐式复制自身,但它会隐式移动。
复制的操作会产生编译时错误,而不是运行时间效率低下。
与拥有 int*
相比,它几乎没有 运行 时间开销,除了销毁时的空检查。它使用的 space 不超过 int*
.
std::vector<int>
存储 3 个指针和隐式副本(这可能很昂贵,并且与您现有的代码行为不匹配)。
我会从 std::unique_ptr<int[]>
开始作为第一关并使其正常工作。在我认为智能缓冲区管理值得之后,我可能会将一些代码转移到 std::vector<int>
。
实际上,作为第一步,我会寻找 memcpy
和 memset
以及类似的函数,并确保在我开始添加 RAII 成员之前它们不在有问题的结构上运行.
A std::unique_ptr<int[]>
表示为结构默认创建的析构函数将为您执行 RAII 清理,而无需编写任何新代码。
我正在使用一个代码库,该代码库编写得很糟糕并且存在大量内存泄漏。
它使用了很多包含原始指针的结构,这些结构主要用作动态数组。
虽然结构经常在函数之间传递,但这些指针的分配和释放是随机放置的,不容易tracked/reasoned/understood。
我将它们中的一些更改为 类 并且那些指针将由 类 自己 RAIIed。它们工作得很好,看起来也不是很丑,除了我禁止复制构造和复制赋值那些 类 只是因为我不想花时间实现它们。
现在想想,我是不是在重新发明轮子?为什么不用 std:array 或 std::valarray 替换 C 风格的数组?
我更喜欢 std::valarray 因为它使用堆内存和 RAIIed。 std::array 在我的开发环境中(还)不可用。
Edit1: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
是一些 "weird" 数学向量,用于进行类似数字计算的事情。它并不是真正设计用于存储任意对象的数组。
也就是说,使用 std::vector
很可能是一个 非常 的好主意。它将修复您的泄漏、使用堆、可调整大小、具有出色的异常安全性等等。
它还保证数据存储在一个连续的内存块中。您可以使用 data()
成员函数获取指向所述块的指针,或者,如果您是 C++11 之前的版本,则使用 &v[0]
获取非空向量 v
。然后您可以像往常一样使用它处理指针业务。
我更喜欢std::vector
as the replacement of c-style arrays. You can have a direct access to the underlying data (something like bare pointers) via .data()
:
Returns pointer to the underlying array serving as element storage.
std::unique_ptr<int[]>
接近拥有 int*
的替代品。它有一个很好的 属性,它将 不会 隐式复制自身,但它会隐式移动。
复制的操作会产生编译时错误,而不是运行时间效率低下。
与拥有 int*
相比,它几乎没有 运行 时间开销,除了销毁时的空检查。它使用的 space 不超过 int*
.
std::vector<int>
存储 3 个指针和隐式副本(这可能很昂贵,并且与您现有的代码行为不匹配)。
我会从 std::unique_ptr<int[]>
开始作为第一关并使其正常工作。在我认为智能缓冲区管理值得之后,我可能会将一些代码转移到 std::vector<int>
。
实际上,作为第一步,我会寻找 memcpy
和 memset
以及类似的函数,并确保在我开始添加 RAII 成员之前它们不在有问题的结构上运行.
A std::unique_ptr<int[]>
表示为结构默认创建的析构函数将为您执行 RAII 清理,而无需编写任何新代码。