我有一个小测试程序,可以将值插入到QVector中。QVector在开始时被保留,以便分配最小的内存量。我验证了容量是正确的,并且QVector的大小没有超过容量。
我注意到,将数据附加到QVector并不会更改第一个元素的地址。到目前为止一切都很好。
然后,我使用QSplineSeries类的替换()方法将数据从向量复制到图表。在调用此方法后,我再次检查QVector中第一个元素的地址,令我感到惊讶的是,地址已经更改了!
在每次调用该方法时都会发生这种情况,我想了解为什么会发生这种情况。我怀疑可能与Qt容器的隐式共享有关,但我不明白为什么要更改这个容器的地址。
示例代码和输出如下所示。
#include <QApplication>
#include <QDebug>
#include <QtCharts/QChart>
#include <QtCharts/QChartView>
#include <QtCharts/QSplineSeries>
#include <memory>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
auto chart = std::make_unique<QtCharts::QChartView>(new QtCharts::QChart());
chart->chart()->addSeries(new QtCharts::QSplineSeries);
QVector<QPointF> vector;
vector.reserve(1000);
while (true) {
vector.append(QPointF(0, 0));
qDebug() << "1. Size: " << vector.size() << " Capacity: " << vector.capacity();
qDebug() << "1. Address of first element: " << &vector[0];
auto series = dynamic_cast<QtCharts::QSplineSeries*>(chart->chart()->series().at(0));
series->replace(vector);
qDebug() << "2. Size: " << vector.size() << " Capacity: " << vector.capacity();
qDebug() << "2. Address of first element: " << &vector[0];
}
return a.exec();
}输出
链接到QSplineSeries::QVector(此处)调用的源代码
编辑
我刚刚意识到,在QSplineSeries::QVector中调用了这的赋值运算符,它看起来像这。这意味着QSplineSeries中的内部向量复制我传入的QVector,但我仍然不明白为什么传入的QVector更改它的地址。
发布于 2019-09-14 02:54:15
您已经遇到了Qt容器与标准库容器不同的一种方式。具体来说,Qt使用的是隐式共享和在写上复制。这意味着当容器的副本被复制时,副本和原始数据都指向相同的数据。只有在试图更改其中一个容器的内容时,才会进行深度复制。(被更改的容器获取其数据的新地址,即使它是原始容器。)
让我们将此应用于您的示例。首先,您将获得QVector的统计数据。接下来你叫QSplineSeries::replace(QVector<QPointF>)。此函数的目的是将提供的QVector复制到QSplineSeries的数据中。此副本将保留该函数的返回。(该参数还创建了向量的副本--它不是通过引用传递的--但是该副本在函数返回时被销毁。)因此,当您进入下一行时,vector将与另一个容器共享数据,特别是chart内部的容器。到现在为止还好。
检查vector的大小和容量仍然很好。但是,您使用operator[]。这将返回对向量元素的非常量引用。这意味着你可以写信给它。不管你是否真的写信给它。对象无法知道您将如何处理引用,因此它必须为潜在的写入做好准备。由于数据是共享的,因此将触发深度副本。vector中的数据被复制到一个新的内存块中,您可以在不影响chart的情况下覆盖它。因此,内存地址会发生变化。
如果您想在不触发深度复制的情况下完成分析,请将&vector[0]更改为&vector.at(0)或vector.constData()。它们提供了对数据的const-qualified访问,因此不会触发深度复制。
注意:由operator[]使用的const QVector版本返回一个常量引用,因此不会触发深度副本。const的非__ vector性质是这里的一个因素。
https://stackoverflow.com/questions/57931574
复制相似问题