Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 返回迭代器与松耦合_C++_Data Structures_Iterator - Fatal编程技术网

C++ 返回迭代器与松耦合

C++ 返回迭代器与松耦合,c++,data-structures,iterator,C++,Data Structures,Iterator,我有一个关于我正在编写的数据结构体系结构的问题。我正在编写一个图像类,我将在一个特定的算法中使用它。在这个算法中,我需要触摸图像中某个边界内的每个像素。我知道的实现这一点的经典方法是使用两个嵌套for循环: for(int i = ROW_BORDER; i < img->height - ROW_BORDER; i++) for(int j = COL_BORDER; j < img->width - COL_BORDER; j++) WHATE

我有一个关于我正在编写的数据结构体系结构的问题。我正在编写一个图像类,我将在一个特定的算法中使用它。在这个算法中,我需要触摸图像中某个边界内的每个像素。我知道的实现这一点的经典方法是使用两个嵌套for循环:

for(int i = ROW_BORDER; i < img->height - ROW_BORDER; i++)
    for(int j = COL_BORDER; j < img->width - COL_BORDER; j++)
        WHATEVER 
for(inti=ROW\u BORDER;iheight-ROW\u BORDER;i++)
对于(int j=COL_BORDER;jwidth-COL_BORDER;j++)
无论什么
然而,有人告诉我,在STL样式中,通常最好返回迭代器,而不是像上面那样使用循环。这将很容易得到一个迭代器来查看图像中的每个像素,甚至可以很容易地合并边界约束,但我感觉包含的边界将松散耦合吹出水面

所以,问题是,我应该返回一个特殊的“border excluding iterator”,使用for循环,还是有更好的方法我没有想到


为了避免类似“好吧,只使用OpenCV或VXL!”,我实际上并没有编写图像类,而是编写了一个高斯金字塔的差分,用于特征检测器。也就是说,同样的问题也适用,编写两个for循环比编写三个或四个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是一个基类,可以派生它来生成许多不同的边界约束。
我的理由是迭代器以不同的方式进行迭代,但我认为他们不需要了解您的业务逻辑。可以通过上面的约束将其抽象为另一个设计构造。

对于位图数据,值得注意的是,在流行的图像处理API中,没有常用的基于迭代器的算法或数据集。这应该是一个线索,说明很难像常规二维数组。(谢谢)

如果您确实需要/更喜欢图像无边框迭代器,您应该发明一个新概念来进行迭代。我的建议类似于一个图像区域

class ImageArea: Image
{  int clipXLeft, clipXRight;
   int clipYTop, clipYBottom;
  public:
   ImageArea(Image i, clipXTop ... )
然后从那里构造迭代器。然后,迭代器可以透明地处理图像或图像中的区域


另一方面,基于常规x/y索引的方法也不错。迭代器对于抽象数据集非常有用,但是当您自己实现迭代器时会付出代价

要想有可重用的东西,我需要一个函数

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),我保证这将提供比迭代器更好的性能,迭代器需要对每次迭代进行额外检查


另一方面,迭代器将使您的东西可以使用标准算法,如
std::transform
,如果不需要像素位置,并且您的数据中没有大间距,您可以使迭代器的速度几乎一样快(间距用于对齐,通常在图形硬件表面上找到).

您希望迭代器和yoru类之间还是迭代器和迭代器用户之间存在松耦合?通常,迭代器封装了所有不干净的细节,并且与数据结构紧密耦合。我的意思是类和算法之间的松散耦合。数据结构应该是独立的,对吗?因此,对于我来说,在这种特殊情况下构建迭代器对于某种特殊情况来说似乎很奇怪。我觉得使用一种特殊的方法“get_bordered_iterator”或者仅仅针对这种算法的东西不是最好的风格。对于二维图像,我只使用索引而不是迭代器。也使用索引。@anjruu:像素的顺序重要吗?如果不是,则只是某个迭代器以未指定的顺序(从迭代器用户的pov)遍历所有像素。这似乎与哈希表上的迭代器一致。酷,我以前从未听说过!如果你想要最好的表现,那似乎是个糟糕的主意。通常,图像处理需要很长的时间和开销,例如虚拟函数调用(尤其是每像素调用!)可以更好地避免dvisitor模式听起来有点不典型,因为没有层次结构,只有一种类型可以访问。但我不是一个模式律师。@kotlinski如果你使用模板,它不是一个虚拟函数调用;phresnel的回答给出了visitor模式的示例实现,但当您自己实现它们时会付出代价。当标准库实现它们时,没有特殊的技术,因此成本将大致相同。@MatthieuM。开发成本一般。但是,在这种情况下,需要考虑二维剪裁。1-重复数据以进行迭代(mem+复制成本)2-计算转换(it++成本)。什么是难以实现的
如果(++x==width){x=0;++y;}
?@phresnel是的,那么在++it上有一些额外的条件。我并不是建议将平面图像区域放大/透镜放大到极限=)@CaptainGiraffe:很好地引用了菲涅耳透镜:D(我的昵称实际上是基于爱好者在真实图像合成方面的努力)@MatthieuM。我猜在上面的代码中不需要,一个简单的边界约束bc;应该足够了,但假设用户将向某个方法传递BorderConstraint指针或引用
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; });