繁体   English   中英

如何动态存储 QVector 的地址<T>在另一个 QVector <QVector<T> *&gt;?

[英]How to dynamically store address of a QVector<T> in another QVector<QVector<T>*>?

我正在处理大量数据,例如 100,000 个双精度值,每 100 毫秒左右收集一次。 我必须在任何给定时间在我的软件中存储 25 个甚至更多这些生成的数据。 每次采集的数据长度和采集次数都因当前情况而异。 我不想将我的数据存储为QVector<QVector<double>>因为QVector将数据存储在相邻的内存位置,每次添加QVector<double>QVector<QVector<double>>导致整个事物被复制到一个新的给定的位置,导致巨大的滞后(特别是如果已经有 20 个QVector<double>并且我正在添加第 21 个)。

我的解决方案是将给定的数据存储为QVector<QVector<double>*>即每次数据采集我只是将地址存储到QVector以用于当前采集。 但是,我希望它独立地存储在QVector<QVector<double>*>即只要我不清除指针就可以访问数据。 我无法弄清楚如何做到这一点。 我尝试了多种方法。 假设我声明QVector<QVector<double>*> myVec; 在我的.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()退出, tempVec被销毁。

void MainWindow::addData()
{
    QVector<double> tempVec; // Create a temprory vector
    tempVec << 2.7 << 3.4 << 4.5;
    myVec << &QVector(tempVec);
}

我认为这会起作用,因为我没有存储tempVec的地址,而是在新的QVector复制tempVec并将其地址分配给myVec ,但它也会引发异常。

有什么办法可以将QVector纯粹存储另一个QVector指针

您将地址存储到然后被销毁的对象中。 这意味着您的指针向量包含悬空指针:

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路由,它会自动为你删除指针。

最后,这在您的情况下可能更可取,您可以完全避免使用指针,并通过使用std::move()将向量转换为右值来将向量移动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 ),它处于有效但未指定的状态(通常为空)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM