简体   繁体   English

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

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

I am working with large amounts of data, something like 100,000 double values, being gathered every 100 milliseconds or so.我正在处理大量数据,例如 100,000 个双精度值,每 100 毫秒左右收集一次。 I have to store 25 or even more of these generated data in my software at any given time.我必须在任何给定时间在我的软件中存储 25 个甚至更多这些生成的数据。 Both, the data length on each acquisition as well as the number of acquisitions varies depending on the current situation.每次采集的数据长度和采集次数都因当前情况而异。 I do not want to store my data as QVector<QVector<double>> because QVector stores data in adjacent memory locations and each addition of QVector<double> to QVector<QVector<double>> results in the entire thing being copied to a new location given, resulting in huge lags (especially if there is already 20 QVector<double> present and I am adding the 21st one to it).我不想将我的数据存储为QVector<QVector<double>>因为QVector将数据存储在相邻的内存位置,每次添加QVector<double>QVector<QVector<double>>导致整个事物被复制到一个新的给定的位置,导致巨大的滞后(特别是如果已经有 20 个QVector<double>并且我正在添加第 21 个)。

My solution is to store the given data as QVector<QVector<double>*> ie each data acquisition I am just storing the address to the QVector for the current acquisition.我的解决方案是将给定的数据存储为QVector<QVector<double>*>即每次数据采集我只是将地址存储到QVector以用于当前采集。 However, I want it to be stored in QVector<QVector<double>*> independently ie as long as I don't clear the pointer I am able to access the data.但是,我希望它独立地存储在QVector<QVector<double>*>即只要我不清除指针就可以访问数据。 I am unable to figure out how to do this.我无法弄清楚如何做到这一点。 I have tried multiple methods.我尝试了多种方法。 Let's say I declare QVector<QVector<double>*> myVec;假设我声明QVector<QVector<double>*> myVec; in my .h file and I use a function to new add data to it on each acquisition like this (below function is just for testing, that's why I am creating data inside the function):在我的.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;
}

This doesn't work, most of the time it throws an exception, and a few times it just shows some garbage value.这不起作用,大多数时候它会抛出异常,有几次它只是显示一些垃圾值。

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

This also doesn't work, of course, because tempVec is destroyed as soon as addData() is exited.当然,这也不起作用,因为tempVec addData()退出, tempVec被销毁。

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

I thought this would work as I am not storing the address of tempVec but rather copying tempVec in a new QVector and assigning its address to myVec , but it is also throwing an exception.我认为这会起作用,因为我没有存储tempVec的地址,而是在新的QVector复制tempVec并将其地址分配给myVec ,但它也会引发异常。

Is there any way I can store QVector purely as pointers inside another QVector ?有什么办法可以将QVector纯粹存储另一个QVector指针

You're storing addresses to objects that are then destroyed.您将地址存储到然后被销毁的对象中。 That means your vector of pointers contains dangling pointers:这意味着您的指针向量包含悬空指针:

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;
}

I'm surprised your compiler even accepts this code, since taking the address of a temporary should be a compilation error.我很惊讶你的编译器甚至接受了这段代码,因为获取临时地址应该是一个编译错误。 Naming the temporary allows it to compile, but it's not any better, since you still get a dangling pointer:命名临时文件允许它编译,但也好不到哪里去,因为您仍然会得到一个悬空指针:

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

If you store a pointer to an object, you need to make sure this object still exists whenever you access that pointer.如果存储指向对象的指针,则需要确保在访问该指针时该对象仍然存在。

One way around this would be to allocate each vector with new before storing its address.解决此问题的一种方法是在存储其地址之前用new分配每个向量。 But then you need to remember to delete it when you no longer need the pointers.但是,当您不再需要指针时,您需要记住将其delete Instead of that, you can use a smart pointer instead.取而代之的是,您可以使用智能指针。 std::unique_ptr in this case would do the job, but unfortunately QVector cannot store non-copyable elemens.在这种情况下std::unique_ptr可以完成这项工作,但不幸的是QVector无法存储不可复制的元素。 So you'd need std::shared_ptr .所以你需要std::shared_ptr This way, you don't need to store the pointers anywhere else but myVec :这样,除了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;
}

If you don't absolutely require QVector and can do with std::vector instead, I'd recommend that, since it can store std::unique_ptr elements just fine:如果您不是绝对需要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;
}

If you really need to store raw pointers and can't use smart pointers, then I'm afraid you need to manage the pointed-to objects yourself by allocating them with new and then once you're done with myVec and no longer need it, clean up with delete :如果您真的需要存储原始指针并且不能使用智能指针,那么恐怕您需要通过使用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;
}

Keep in mind that you also need to delete a pointer if you remove it from myVec or override it with a different pointer.请记住,如果您从myVec删除一个指针或使用不同的指针覆盖它,您还需要删除它。 This is tedious and error prone.这是乏味且容易出错的。 When you forget to do it, you leak memory.当你忘记这样做时,你就会泄漏内存。 So I recommend going the unique_ptr route instead, which will automatically delete the pointer for you.所以我建议改为使用unique_ptr路由,它会自动为你删除指针。

Finally, and this might be preferable in your case, you can avoid pointers altogether and move the vector into myVec by casting it to an rvalue using std::move() .最后,这在您的情况下可能更可取,您可以完全避免使用指针,并通过使用std::move()将向量转换为右值来将向量移动myVec Not sure how well QVector works with move semantics, but std::vector does the job just fine, in which case you'd use std::vector for both "inner" and "outer" vectors.不确定QVector与移动语义的工作情况如何,但std::vector可以很好地完成这项工作,在这种情况下,您可以将std::vector用于“内部”和“外部”向量。 As an optimization, if you know the amount of doubles you need to store, you can pre-allocate with reserve() to avoid costly re-allocations when you add elements:作为优化,如果您知道需要存储的双精度数,则可以使用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));
}

With moving, no allocations or copies are performed, if the objects involved support move semantics.移动时,如果所涉及的对象支持移动语义,则不执行分配或复制。 As mentioned, std::vector does.如前所述, std::vector确实如此。

Very important: after an object has been "moved from" ( tmpVec in this case), it's in a valid but unspecified state (usually empty.)非常重要:在对象被“移出”后(在本例中为tmpVec ),它处于有效但未指定的状态(通常为空)。

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

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