我正在处理大量的数据,大约100,000个双值,每100毫秒左右收集一次。我必须在任何时候在我的软件中存储这些生成的数据中的25个甚至更多。两种情况下,每次收购的数据长度以及收购次数都因当前情况而异。我不想将我的数据存储为QVector<QVector<double>>,因为QVector将数据存储在相邻的内存位置,而QVector<double>对QVector<QVector<double>>的每次添加都会导致整个事物被复制到给定的新位置,从而造成巨大的滞后(特别是如果已经有20 QVector<double>,并且我要在其中添加第21QVector<double>)。
我的解决方案是将给定的数据存储为QVector<QVector<double>*>,也就是说,我只是将当前获取的地址存储到QVector。但是,我希望它独立地存储在QVector<QVector<double>*>中,也就是说,只要我不清除指针,我就能够访问数据。我想不出该怎么做。我尝试过多种方法。假设我在我的.h文件中声明了.h,并使用一个函数在每次获取时向它添加新的数据,如下所示(下面的函数只是用于测试,这就是为什么我要在函数中创建数据):
void MainWindow::addData()
{
myVec << &QVector<double>(0) // Creating a new empty vector and storing it's location
*myVec[0] << 2.7 << 3.4 << 4.5;
}这不起作用,大多数情况下它会抛出一个异常,并且有几次它只显示一些垃圾值。
void MainWindow::addData()
{
QVector<double> tempVec; // Create a temprory vector
tempVec << 2.7 << 3.4 << 4.5;
myVec << &tempVec;
}当然,这也不起作用,因为一旦tempVec退出addData(),addData()就会被销毁。
void MainWindow::addData()
{
QVector<double> tempVec; // Create a temprory vector
tempVec << 2.7 << 3.4 << 4.5;
myVec << &QVector(tempVec);
}我认为这样做是可行的,因为我不是存储tempVec的地址,而是将tempVec复制到新的QVector中并将其地址分配给myVec,但它也会引发异常。
是否有任何方法可以将QVector 纯粹作为指针存储在另一个QVector中?
发布于 2020-10-04 14:49:19
您正在存储对象的地址,然后这些对象被销毁。这意味着您的指针向量包含悬空指针:
void MainWindow::addData()
{
myVec << &QVector<double>(0);
// the temporary vector is destroyed here and myVec contains a
// dangling pointer
*myVec[0] << 2.7 << 3.4 << 4.5;
}我很惊讶您的编译器竟然接受这段代码,因为获取临时地址应该是编译错误。临时命名允许编译,但也没有什么更好的,因为仍然有一个悬空指针:
void MainWindow::addData()
{
QVector<double> tempVec(0);
myVec << &tempVec;
*myVec[0] << 2.7 << 3.4 << 4.5;
} // <-- tempVec is destroyed here, so you get a dangling pointer如果存储指向对象的指针,则需要确保无论何时访问该指针,该对象仍然存在。
解决这一问题的一种方法是在存储地址之前用new分配每个向量。但是,当您不再需要指针时,您需要记住delete。相反,您可以使用智能指针代替。在这种情况下,std::unique_ptr可以完成任务,但不幸的是,QVector不能存储不可复制的精灵。所以你需要std::shared_ptr。这样,您不需要将指针存储在其他任何地方,只需存储myVec
#include <memory>
QVector<std::shared_ptr<QVector<double>>> myVec;
// ...
void MainWindow::addData()
{
myVec << std::make_shared<QVector<double>>(0);
*myVec[0].get() << 2.7 << 3.4 << 4.5;
}如果您不完全需要QVector,并且可以使用std::vector,我建议您这样做,因为它可以很好地存储std::unique_ptr元素:
#include <memory>
#include <vector>
std::vector<std::unique_ptr<QVector<double>>> myVec;
// ...
void MainWindow::addData()
{
myVec.push_back(std::make_unique<QVector<double>>(0));
*myVec[0].get() << 2.7 << 3.4 << 4.5;
}如果您确实需要存储原始指针,并且不能使用智能指针,那么恐怕您需要通过使用new分配指向对象,然后使用myVec完成并且不再需要时,使用delete进行清理。
QVector<QVector<double>*> myVec;
// ...
void MainWindow::addData()
{
myVec << new QVector<double>(0);
*myVec[0] << 2.7 << 3.4 << 4.5;
}
// Cleanup code you need to call when you no longer need myVec
for (auto ptr : myVec) {
delete ptr;
}请记住,如果从myVec中删除指针或用不同的指针覆盖指针,也需要删除指针。这既乏味又容易出错。当你忘记去做的时候,你就会漏出记忆。因此,我建议选择unique_ptr路由,它将自动为您删除指针。
最后,在您的情况下,这可能更好,您可以完全避免指针,并通过使用将向量转换为rvalue,从而将移动到myVec中。不确定QVector如何处理移动语义,但std::vector做得很好,在这种情况下,您将对“内部”和“外部”向量使用std::vector。作为一种优化,如果您知道需要存储的加倍量,可以使用reserve()预分配,以避免在添加元素时重新分配的代价高昂:
#include <memory>
#include <vector>
std::vector<std::vector<double>> myVec;
// ...
void MainWindow::addData()
{
std::vector<double> tmpVec;
tmpVec.reserve(amount_of_elements);
tmpVec.push_back(2.4);
tmpVec.push_back(3.7);
// etc until filled
myVec.push_back(std::move(tmpVec));
}对于移动,如果涉及到的对象支持移动语义,则不执行分配或副本。正如前面提到的,std::vector是这样做的。
非常重要的是:在对象被“移出”(本例中为tmpVec)之后,它处于有效但未指定的状态(通常为空)。
https://stackoverflow.com/questions/64195788
复制相似问题