【问题标题】:Get permanent pointer to object in list获取指向列表中对象的永久指针
【发布时间】:2015-03-10 14:00:24
【问题描述】:

我目前正在寻找一种在列表中拥有指向对象的永久指针的方法。永久是指一个指针,只要它存在,它就始终指向同一个对象。

我找不到任何简单的方法,所以有人有想法吗?我已经在使用 boost,所以 boost 解决方案也是非常可接受的。

为了更清楚地了解我需要什么,这里有一个例子:

std::map<int, std::list<void (*)()> > handlerList; // I store some callback functions like this

void addHandler( int id, void (*handlerFunc)() ) {
  handlerList[id].push_back(handlerFunc); // 100% intended behavior (I know that the []-operator creates a object if it doesn't exist)
}

我想要的是这样的:

some_permanent_pointer_type addHandler( int id, void (*handlerFunc)() ) {
  return handlerList[id].push_back(handlerFunc);
}

然后在其他时候:

some_permanent_pointer_type handlerPointer;

handlerPointer = addHandler( 123, someFunc );

// Other point of code

handlerPointer.delete(); // or
ListType.delete(handlerPointer); // Or something like this

有人知道吗?编写我自己的课程并不是什么大不了的事。但我不知道如何实现这一点。但我更喜欢已经存在的东西。时间和东西。

注意:此代码将在 linux 机器上运行。

【问题讨论】:

  • 你不能这样做,因为列表是可变的。如果列表发生变化,其对象在内存中的位置可能会发生变化。您已经可以通过 id 查找处理程序列表,因此您可以在需要时获取它。每当我看到这样的问题时,我发现最好的办法就是退后一步,问问你想做什么,因为答案并不在这条路上。
  • 你在找delegates?
  • @FelixCastor 代表是 C++/CX,与常规 C++ 不同。
  • @mbgda 我看不到任何其他方法可以简单地删除基本上任何给定的处理程序。由于其中一些需要在一段时间后删除。
  • @BrainStone,此类问题的常见解决方案是返回一个唯一令牌(通常只是一个 int 或 uint),用于标识特定的 id 和回调对。当您需要删除它时,您可以说myListType.Delete(token) - 您的列表对象将找到与唯一令牌对应的条目并将其删除。

标签: c++ list pointers object boost


【解决方案1】:

这是我快速拼凑起来的东西。目前,调用destroy() 两次是不好的,但这是可以解决的。

#include <map>
#include <list>

std::map<int, std::list<void (*)()> > handlerList;

class HandleHandle {
    public:
        HandleHandle(std::list<void (*)()> &list, std::list<void (*)()>::iterator iterator):
            list_(list),
            iterator_(iterator)
        {}

        void destroy() {
            list_.erase(iterator_);
        }

    private:
        std::list<void (*)()> & list_;
        std::list<void (*)()>::iterator iterator_;
};

HandleHandle addHandler(int id, void (*handlerFunc)()) {
    handlerList[id].push_back(handlerFunc);
    return HandleHandle(handlerList[id], handlerList[id].rbegin().base());
}

void someFunc() {
}

int main() {
    auto handlerPointer = addHandler(123, someFunc);
    handlerPointer.destroy();
}

【讨论】:

  • 但是如果我删除中间的一个对象,所有其他迭代器将不再指向正确的条目,对吗?
  • 来自std::list::erase 的文档:对已擦除元素的引用和迭代器无效。其他引用和迭代器不受影响。
  • 也许destroy()应该设置迭代器指向list_.end(),然后可以用来测试这个HandleHandle是否已经被销毁了。
  • @AaronMcDaid:这肯定是解决问题的一种方法。
  • @BillLynch 我想你刚刚找到了我的解决方案。我明天会测试这段代码。
【解决方案2】:

根据你所说的要求,你只需要

using funclist = std::list<void (*)()>;
std::map<int, funclist > handlerList; // I store some callback functions like this

funclist& addHandler( int id, void (*handlerFunc)() ) {
  handlerList[id].push_back(handlerFunc); // Creates list on demand
  return handlerList[id];
}

auto list5 = addHandler(5, &foo);
addHandler(5, &bar);
list5.clear(); // Clears entire handlerList[5], i.e. &foo and &bar.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-25
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多