【问题标题】:C++ container performance for image representation用于图像表示的 C++ 容器性能
【发布时间】:2014-07-23 00:17:41
【问题描述】:

我正在开发一个需要将原始图像数据写入内存缓冲区的程序。目前我的实现如下所示:

std::unique_ptr<unsigned char[]> _Screen;
...
_Screen.reset(new unsigned char[width * height * 3]);
std::fill(_Screen.get(), _Screen.get() + (width * height), 0);
...
_Screen[(j * _ScreenWidth + i) * 3] = red;
_Screen[(j * _ScreenWidth + i) * 3 + 1] = green;
_Screen[(j * _ScreenWidth + i) * 3 + 2] = blue;

如果可能的话,我真的很想在这里使用一些 STL 容器。直到运行时我才知道屏幕的大小,所以std::array 出来了。应该可以使用std::vector&lt;unsigned char&gt; 重新定义屏幕,如下所示:

std::vector<unsigned char> _Screen
...
_Screen.resize(width * height * 3);

但我想知道元素访问是否会比使用 C 样式数组慢? (我假设重新分配会更慢,但这对于这个应用程序来说是可以的)。

我还想知道做以下事情是否更有意义:

struct Pixel
{
    unsigned char red;
    unsigned char green;
    unsigned char blue;
};
...
std::vector<Pixel> _Screen;
...
_Screen.resize(width * height);
...
_Screen[(j * _ScreenWidth + i)].red = red;
_Screen[(j * _ScreenWidth + i)].green = green;
_Screen[(j * _ScreenWidth + i)].blue = blue;    

但我最终需要转换为 unsigned char 的单个数组,所以虽然这在我的计算过程中更好地代表了数据,但我不确定这会有多难。使用struct 方法会更慢吗?以后使用类似的方法转换为unsigned char 是否安全:

unsigned char *screen = reinterpret_cast<unsigned char *>(_Screen.data());

【问题讨论】:

  • _Screen 这样以下划线后跟大写字母的名称保留给实现。
  • 正如我在对以下答案的评论中提到的那样:“您将失去向量的性能。在 C++ 中,向量的所有元素在调整大小/分配时都设置为 0/default/NULL。对于一个常规数组,情况并非如此。”
  • @MaxEhrlich 当然,来自标准:17.6.4.3.2 全局名称 [global.names] 1 某些名称集和函数签名始终保留给实现: — 每个名称都包含一个双下划线 _ 或以下划线开头后跟大写字母 (2.12) 保留给实现以供任何使用。 — 每个以下划线开头的名称都保留给实现,用作全局命名空间中的名称。
  • @MaxEhrlich 第 17.6.4.3.2 节全局名称有 2 个项目符号,第二个项目符号:“每个以下划线开头的名称都保留给实现,用作全局名称空间中的名称。”正如您所说,指的是全局命名空间,但第一个“包含双下划线 _ 或以下划线后跟大写字母 (2.12) 的每个名称都保留给实现以供任何使用。”为任何用途保留名称。请重读。
  • @MaxEhrlich 这可以帮助stackoverflow.com/questions/228783/…

标签: c++ performance vector containers


【解决方案1】:

std::vector 基本上已经是一个 C 风格的数组,它只是管理块的分配。如果您初始化向量的大小,那么它会分配一次大小,然后您可以直接访问内部数组缓冲区并根据需要直接处理数据,或者您可以使用重载的括号运算符。最后,我不相信你会因为这样做而失去任何明显的表现。这取决于你觉得好看。

至于您的第二个问题,您最好还是坚持第一次迭代以避免并发症。但是,如果您的 Pixel 结构只是三个无符号字符,那么在内存方面它已经与 3 个 uchar 的数组具有相同的格式,因此几乎没有区别,您仍然可以逐个字符地遍历整个内存块并放入它回到图像中,反之亦然。

【讨论】:

  • 谢谢这是我的想法,但我想看看其他人在使用它之前的想法,我可能会使用vector实现
  • 您将失去向量的性能。在 C++ 中,向量的所有元素在调整大小/分配时都设置为 0/default/NULL。对于常规数组,情况并非如此。
  • 但是,由于矢量只调整了一次大小,它实际上并没有考虑到足够的性能损失来最终产生任何影响。
猜你喜欢
  • 1970-01-01
  • 2012-07-05
  • 2018-09-01
  • 1970-01-01
  • 2014-12-26
  • 2014-11-30
  • 2013-09-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多