返回迭代器与松耦合
Returning Iterator vs Loose Coupling
我有一个关于我正在编写的数据结构体系结构的问题。我正在写一个图像类,我将在一个特定的算法中使用它。在这个算法中,我需要触摸图像中某个边界内的每个像素。我知道做这件事的经典方法是使用两个嵌套的for循环:
for(int i = ROW_BORDER; i < img->height - ROW_BORDER; i++)
for(int j = COL_BORDER; j < img->width - COL_BORDER; j++)
WHATEVER
不过,有人告诉我,在STL的风格中,通常最好返回迭代器,而不是像上面那个样使用循环。让迭代器查看图像中的每个像素会很容易,甚至可以很容易地合并边界约束,但我觉得包含边界会让耦合变得松散。
所以,问题是,我应该返回一个特殊的"边界排除迭代器",使用for循环,还是有我没有想到的更好的方法?
为了避免像"好吧,只使用OpenCV或VXL!"这样的事情,我实际上并不是在写一个图像类,我正在写一个用于特征检测器的高斯金字塔差。也就是说,同样的问题也适用,写两个for循环比写三个或四个更简单。
为了有可重用的东西,我会使用map函数。
namespace your_imaging_lib {
template <typename Fun>
void transform (Image &img, Fun fun) {
const size_t width = img.width(),
size = img.height() * img.width();
Pixel *p = img.data();
for (size_t s=0; s!=size; s+=width)
for (size_t x=0; x!=width; ++x)
p[x + s] = fun (p[x + s]);
}
template <typename Fun>
void generate (Image &img, Fun fun) {
const size_t width = img.width(), size = img.height();
Pixel *p = img.data();
for (size_t s=0, y=0; s!=size; s+=width, ++y)
for (size_t x=0; x!=width; ++x)
p[x + s] = fun (x, y);
}
}
需要一些改进。例如,一些系统,如x,y在[0..1).中
然后你可以像这样使用:
using namespace your_imaging_lib;
Image i = Image::FromFile ("foobar.png");
map (i, [](Pixel const &p) { return Pixel::Monochrome(p.r()); });
或
generate (i, [](int x, int y) { return (x^y) & 0xFF; });
如果您需要同时了解坐标(x和y),我保证与每次迭代都需要额外检查的迭代器相比,这将提供更好的性能。
另一方面,迭代程序将使你的东西可以与标准算法(如std::transform
)一起使用,如果不需要像素位置,并且你的数据中没有很大的间距(间距用于对齐,通常在图形硬件表面上找到),你可以使它们几乎同样快。
我怀疑您应该使用访问者模式——而不是返回迭代器或某种项目集合,您应该将要对每个像素/项目执行的操作传递给保存项目的数据结构,数据结构应该能够将该操作应用于每个项目。无论您的数据结构使用for循环还是迭代器遍历隐藏的像素/任何集合,操作都与数据结构解耦。
IMHO有一个触及每个像素的迭代器听起来是个好主意。然而,对我来说,把边界限制包括在内听起来并没有那么吸引人。也许可以尝试实现这样的目标:
IConstraint *bc=new BorderConstraint("blue-border");
for(pixel_iterator itr=img.begin(); itr!=img.end(); itr++) {
if(!bc->check(itr))
continue;
// do whatever
}
其中IConstraint是一个基类,可以派生该基类以生成许多不同的BorderConstraint。我的基本原理是迭代器以不同的方式迭代,但我认为它们不需要了解您的业务逻辑。这可以通过上面的Constraints抽象到另一个设计构造中。
对于位图数据,值得注意的是在流行的图像处理API中没有常用的基于迭代器的算法或数据集这应该是一个线索,表明它很难像常规2D阵列那样高效地实现。(感谢phresnel)
如果你真的需要/更喜欢无边界图像的迭代器,你应该发明一个新的概念来迭代。我的建议是类似于ImageArea。
class ImageArea: Image
{ int clipXLeft, clipXRight;
int clipYTop, clipYBottom;
public:
ImageArea(Image i, clipXTop ... )
然后从那里构造迭代器。迭代器可以是透明的,以处理图像或图像中的区域。
另一方面,基于x/y索引的常规方法也不是一个坏主意。迭代程序在抽象数据集方面非常有用,但当您自己实现它们时会带来成本。
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 如何在c++迭代器类型中包装std::chrono
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 对于set上的循环-获取next元素迭代器
- 为什么output_editor Concept不需要output_e迭代器标记
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 使用迭代器时如何访问对象在向量中的位置?
- std::vector::迭代器是否可以合法地作为指针
- 跟随整数索引列表的自定义类迭代器
- 不明白迭代器,引用和指针失效,一个例子
- 我可以使用反向迭代器作为ForwardIt吗
- ESP8266单片机矢量迭代器的C++问题
- 如何在C++中将迭代器作为函数参数传递
- 是否应避免从非常量迭代器转换为常量迭代器?
- 如何在 c++ 中将字符串迭代器变量传递给函数?
- 为什么 vector 的随机访问迭代器给出与指针不同的内存地址?
- 返回迭代器与松耦合