在C ++中生成和重用唯一ID

时间:2012-12-04 11:48:38

标签: c++

我正在制定一项要求,其中请求应具有从-2到-101的唯一编号,即一次只有100个请求。如果在给定时间有超过100个请求,那么我应该发送错误。最初我没有要求。一旦我发出请求,我将采用唯一的数字说-2,-3等等。这里的要求是我可能从客户端获取命令没有向服务器发送请求例如-2所以我应该删除这个请求,我应该重用这个号码以备将来请求。

在C ++中实现此功能的最佳方法是什么?

另外,我不应该使用Boost。

4 个答案:

答案 0 :(得分:3)

扩展我的std::bitset评论:

您可以使用id作为bitset的索引和值(true/false)作为id的可用性。

class IdStorage {
    const int N = 100;
   std::bitset<N> ids;

   bool allIdsUsed() { 
       return ids.all();
   }

   int getId() {
     if(allIdsUsed())
         throw "Error";

     for(int i = 0; i < N; ++i )
        if(ids.test(i))
            return i - 2;
   }

   void releaseId(int i) {
       ids.set(i + 2);
    }

}

请注意,在课堂上键入此内容,不在我的脑海中。查看documentation

答案 1 :(得分:2)

您必须至少维护一组未使用的ID。另外,我会抛出一个查找表来验证是否发出了一个id(为了健壮性)。对于两者,我建议使用std::vector,而不是列表。

首先,将未使用的集合存储在std::vector<int>中,您可以很容易地初始化它:

class IdStore {
  private:
    std::vector<int> unused;
    static int const MIN_ID = -101;
    static int const MAX_ID = -2;
  public:
    IdStore::IdStore()
    : unused(MAX_ID - MIN_ID + 1) {
      for (auto i = 0; i <= MAX_ID-MIN_ID; ++i) {
        unused[i] = i;
      }
    }
    int getId();
    void releaseId(int);
};

此外,您可能希望跟踪使用过的ID,以便验证它们是否已分发;我使用了std::vector<bool> used;成员,您可以使用used(MAX_ID - MIN_ID +1)初始化,因为其值最初都默认为false。当然,您可以将used设为bitset,但请注意,这需要在编译时知道从MIN_IDMAX_ID的距离。

从那里分发东西很简单:

int IdStore::getId() {
  if (unused.empty())
    throw "error"; // put something better here
  auto r = unused.back();
  used[r] = true;
  unused.pop_back();
  return MIN_ID + r;
}

然后发布它们:

void IdStore::releaseId(int id) {
  if (id < MIN_ID || id > MAX_ID)
    throw "error"; // put something better here
  id -= MIN_ID;
  if (!used[id])
    throw "error"; // put something better here
  used[id] = false;
  unused.push_back(id);
}

请注意,不会发生重新分配!与使用列表的方法相反,向量将keep its size,而getIdreleaseId都不需要对mallocfree进行昂贵的调用。

答案 2 :(得分:1)

只有100个数字可能没有明显的性能差异,您可以使用集合或数组;像id_used[100]这样的普通旧数组可能会在性能测量中获胜。

如果您需要可扩展的解决方案,请尝试使用“free-set”和“used-set”,其中包含可供使用的自由设置存储ID,以及已使用id的已使用集合。使用id后,将其存储回自由集。

对于允许的id与并发使用的足够大的比率,仅使用“used-set”,并使用拒绝采样来查找空闲ID:

do {
    id = generate_id();
} while(std::end != used_set.find(id));

无论如何,没有明确的答案。

答案 3 :(得分:0)

我没有编译它,但它应该是这样的:

std::list<int> list;
for(int i=start; i<=end; ++i)
  list.insert(i);

//when get Id request
Id2send = list.first();
list.remove(list.first());

//when delete id request
list.remove(id);

//when add id request (this happens when an id is freed or other times)
list.add(id);