0

给 C++ 专家的一个快速问题:

在我正在处理的项目中,有一个类包含指向向量中对象的指针:

    std::vector<object*> objects;

并且有一个向对象添加偏移量的结构(Point2D 显然是 x,y 坐标)

    struct DraggedObject{
    object* obj;
    Point2D offset;

    DraggedObject():obj(NULL),offset(Point2D(0,0)){}
};

每当您拖动一个对象时,它会将其添加到如下所示的 std::map 中:

    std::map <int, DraggedObject> dragged_objects;

所以我的问题是:有一个循环,我需要在其中移动这些对象,但跳过拖动的对象。我的问题是:有没有办法遍历对象向量并找出对象是否在 dragged_object 地图上?

我正在做这样的事情:

for(std::vector<object*>::iterator it = objects.begin(); it != objects.end(); it++){
    if(//Object is not in dragged_objects){
        (*it)->move_to( Point2D( //Some point);
    }else{
        (*it)->move_to (Point2D (//Point of dragged object);
}

但是我不知道如何进行这种比较...

对不起新手问题。

4

7 回答 7

2

std::map 针对按键快速查找(在本例中为 int 值)而不是按值快速查找(您的对象*)进行了优化。所以你唯一的选择是迭代整个地图直到你找到它。当映射很小并且代码部分对性能不是很重要时,您可以这样做。当性能很重要时,您可以添加一个额外的 std::set 并将所有当前正在拖动的对象存储在其中,或者您可以让对象本身知道它们当前是否正在被拖动,并添加一个 isDragged() 方法到您的对象类。

于 2013-01-11T09:15:58.190 回答
0

您可以更改方法并迭代拖动对象的地图,对每个拖动对象执行您需要完成的工作,然后将对象添加到临时std::vector<object*>. 当你的循环完成后,你可以通过你的向量,只对不在你的临时向量中的元素做一些事情。

于 2013-01-11T09:16:02.043 回答
0

我相信您也许可以使用set_difference。您将必须实现自定义比较器,还必须对向量中的元素进行排序。除非您这样做,否则我认为您没有比对向量中的每个元素执行查找以验证它是否存在于地图中更好的方法了。

于 2013-01-11T09:20:34.373 回答
0

如果可能的话,mapobject*键(例如,std::map <object*, DraggedObject>而不是std::map <int, DraggedObject>. 然后你可以这样写if

 if(dragged_objects.count(*it)){
        (*it)->move_to( Point2D( //Some point);
    }else{
        (*it)->move_to (Point2D (//Point of dragged object);
于 2013-01-11T09:21:39.133 回答
0

您可以使用的一种方法是将向量替换为列表,并让此列表仅包含未拖动的对象。

然后你会遍历这个列表。如果您想要所有对象,则遍历 ilst 和地图。不确定顺序对于这样做有多重要,但如果对象的 id 很重要(您存储在地图中),您可以根据地图中的 id 迭代“合并”列表和地图。

在这种情况下,列表比向量更好的原因是,如果您将对象拖出集合的中间,从列表中删除是恒定的时间。

于 2013-01-11T09:28:44.970 回答
0

既然你说对象 ID 是他们在dragged_objects地图中的关键,你可以使用find地图的方法。我相信它应该是这样的。

std::map::iterator miter;
for (auto &obj : objects)
{
    miter = dragged_objects.find(obj.id);
    if (miter != dragged_objects.end()) {
        /* do for non-dragged objects */
    } else {
        /* do for dragged objects */
    }
}

根据需要调整非 C++11 编译器。

于 2013-01-11T09:34:31.380 回答
0

Where does the int come from which is used to index into the map? If it's an identifier extracted from object, then all you have to do is extract it in your loop, and see if it is present in the map (using map::find). Otherwise, you'll either need an additional map, indexed with object*, or you'll need to iterate through all of the dragged_objects, looking at each one to see if it has the address you want (std::find_if). Depending on the number of dragged_objects, this could be slow; but normally, I'd guess that dragged_objects is either empty or only has a single entry. If this is the case, the linear search each time through your loop is perfectly acceptable.

于 2013-01-11T09:37:47.250 回答