我目前处理一些数据记录,使用缓冲区,即在录制期间,数据存储在map
中,当录制结束时,此地图用于构建CaptureRecord
被推送到全局记录(类型std::vector<CaptureRecord>
),该记录存储到目前为止完成的每个记录。
最后一部分的代码如下所示:
void CaptureRecorder::stopDataRecording()
{
OutputDebugString(L"Stopping data recording\n");
//Omitted stuff
//The CaptureRecord ctor takes a map as parameter
m_globalRecord.emplace_back(m_currentCaptureElements);
m_currentCaptureElements.clear();
//Omitted stuff
}
问题在于,如果这两行看起来需要花费一些时间(最多几秒),那么时间会与记录的大小成比例增加(这使我很明显这里的副本有问题)
所以我想要做的是,在通过CaptureRecord
创建emplace_back()
时,它会拥有m_currentCaptureElement
中包含的日期的所有权。事实是,我真的不知道该怎么做。我尝试使用移动语义,即使用std::move()
作为emplace_back()的参数,以及CaptureRecord
的ctor的以下代码:
CaptureRecord(std::map<int, ProcessedCaptElem> record):
recordContent(std::move(record))
{
for(auto& recordElement : recordContent){
m_timestamps.emplace_back(recordElement.second.timestamp);
m_intensities.emplace_back(recordElement.second.calculatedIntensity);
}
}
但它似乎没有任何影响(这让我相信它仍然“无法”从变量m_currentCaptureElements
移动。)
所以我的问题是:
是否可以做这样的事情(从某种缓冲区移动,然后重置它)以及如何做?
注意:我完全接受不涉及移动语义的建议。这些是我能想到的最接近传递数据而不复制的数据,但可能还有其他解决方案,我可能已经错过了不涉及移动。
答案 0 :(得分:2)
首先,您要将m_currentCaptureElements
的内容传输到另一个对象。所以你需要move
它。
m_globalRecord.emplace_back(std::move(m_currentCaptureElements));
m_currentCaptureElements.clear();
现在,为了利用赋予CaptureRecord
构造函数的rvalue映射,您需要一个构造函数重载,它接受对映射的右值引用。
CaptureRecord(std::map<int, ProcessedCaptElem>&& record):
recordContent(std::move(record))
{
// ...
}
如果您需要在地图外单独存储时间戳和计算强度的副本,则无法从地图中移动项目,前提是您还要保留地图的副本。如果您不需要地图,可以将构造函数更改为
CaptureRecord(std::map<int, ProcessedCaptElem>&& record)
{
for(auto&& recordElement : record){
m_timestamps.emplace_back(std::move(recordElement.second.timestamp));
m_intensities.emplace_back(std::move(recordElement.second.calculatedIntensity));
}
}
假设您还需要一个带左值的重载,您可以创建另一个将项目复制出地图的构造函数。
CaptureRecord(std::map<int, ProcessedCaptElem> const& record)
recordContent(record)
{
for(auto const& recordElement : recordContent){
m_timestamps.push_back(recordElement.second.timestamp);
m_intensities.push_back(recordElement.second.calculatedIntensity);
}
}
答案 1 :(得分:1)
我不清楚你正在处理的某些类型是什么,以及某些事情是如何构建的。但是从我可以收集的内容来看,你的CaptureRecord
构造函数几乎是正确的。你错过了什么std::move
s ...
m_timestamps.emplace_back(std::move(recordElement.second.timestamp));
m_intensities.emplace_back(std::move(recordElement.second.calculatedIntensity));
此外,您可以reserve
m_timestamps
和m_intensities
。这可能有助于提高性能。您还必须通过CaptureRecord
构建std::move
地图...
CaptureRecord cap(std::move(myMap));
在任何地方使用std::move
您的意思是将所有权从一个地方转移到另一个地方。另外需要注意的是,您std::move
的任何对象都必须具有移动构造函数/移动赋值运算符。如果您正在使用VS,它将不会像复制构造函数/复制赋值运算符那样为您生成它们。这应该。它没有。你必须明确地做到这一点。