Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.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++_Multithreading_Locking_Mutex - Fatal编程技术网

C++ 线程安全读取类成员向量而不进行复制

C++ 线程安全读取类成员向量而不进行复制,c++,multithreading,locking,mutex,C++,Multithreading,Locking,Mutex,假设我有一门课: class A { private: std::vector<MyObject> history; std::mutex historyLock; } 我的直觉告诉我在类a中公开一个名为GetHistory()的方法,该方法将锁定互斥锁,复制列表并返回副本 有没有一种方法可以在不产生复制操作成本的情况下读取B类列表?有几种方法可以解决此类问题。一种方法是使用更复杂的结构来存储历史,就像一个不可变的向量。(对于廉价拷贝,不可变向量的迭代迭代性能)但

假设我有一门课:

class A
{
   private:
   std::vector<MyObject> history;
   std::mutex historyLock;
}
我的直觉告诉我在
类a
中公开一个名为
GetHistory()
的方法,该方法将锁定互斥锁,复制列表并返回副本


有没有一种方法可以在不产生复制操作成本的情况下读取B类列表?

有几种方法可以解决此类问题。一种方法是使用更复杂的结构来存储历史,就像一个不可变的向量。(对于廉价拷贝,不可变向量的迭代迭代性能)但是使用标准C++,我认为最简单的方法是将一个遍历成员函数模板添加到接受回调:
template <class F> void TraverseHistory(F&& callback)
{
  std::lock_guard guard{ historyMutex };
  for (auto const& item : history)
  {
    callback(item);
  }
}
另一种选择是将对整个向量的引用传递给回调。使用这种方法,函数模板将如下所示:

template <class F> void ReadHistory(F&& callback)
{
  std::lock_guard guard{ historyMutex };
  callback(std::as_const(history));
}
template void ReadHistory(F&&callback)
{
std::lock_guard guard{historyMutex};
回调(std::as_const(history));
}

为什么是第二个类?@MichaelSurette类a可能是某种驱动程序,类B可能是it的可选GUI感谢您的回答,在我的用例中,这是一种可能的解决方案。但是,如果我想做一些类似搜索它的事情呢?还是向后迭代?我将被迫为该向量的每个操作生成一个类似的函数。如果这是其他用户的API,我将强制用户以某种方式迭代该结构。有没有一种方法可以让我既吃蛋糕又吃蛋糕呢?我的意思是说,是的,这是可行的,但迫使我在向量上实现一系列操作,这可能只在有限的用例中有用。我无法预见API用户可能希望对该向量执行什么操作,因此通过强制他们这样使用它,我限制了他们很好地处理该向量的能力。例如,假设历史向量有2GB的数据,用户(类B)希望使用自己的特殊类型的搜索算法来搜索它。如果不复制这个解决方案,他们就无法实现这一点。我觉得这个解决方案并不完全现实。然而,您不必一次传递一个元素。我已经用这种方式展示了它,因为它通常是最简单的方法。但是您也可以传递对整个向量的引用。传递对向量的引用应该与回调一起使用,谢谢!
void TraverseHistory(std::function<void(MyObject const&)> const& callback);
template <class F> void ReadHistory(F&& callback)
{
  std::lock_guard guard{ historyMutex };
  callback(std::as_const(history));
}