C++:传递指向函数中类的指针会导致数据复制?

C++: passing a pointer to a class in a function results in data copy?

本文关键字:指针 数据 复制 函数 C++      更新时间:2023-10-16

在我的Qt5应用程序中,我有一个类'Image',其中包含一个带有像素值的一维向量,以及一个减去参考图像的成员函数,如下所示:

class Image {
public:
QVector<float> pixels;
void subtract(Image *refImage) {
long i = 0;
for (auto &pix : pixels) {
pix -= refImage->pixels[i];
++i;
}
}
}

我还有一个类"数据",包含一个指向参考图像的指针:

class Data {
public:
Image* refImage;
}

最后,在我的主函数中,我像这样从图像中减去参考图像:

int main() {
...
Image *image = new Image(args);
Data *referenceData = new Data(args);
image->subtract(referenceData->refImage);
...
}

由于我正在传递一个指向减法((的指针,因此我不希望制作refImage的副本。但是,我观察到的是,对于每次调用减去((,我的应用程序的内存占用量都会增加大约"refImage"的大小。我不明白这一点。我认为通过将指向函数的类的指针传递给函数,我可以避免复制?

您可能遇到过Qt容器与标准库容器的不同之处之一。具体来说,Qt使用隐式共享和写入时复制。这意味着,当创建容器的副本时,副本和原始副本都指向相同的数据。只有当尝试更改其中一个容器的内容时,才会进行深层复制。(虽然修剪后的示例没有显示正在制作的副本,但很可能复制正在实际代码中的某个地方进行。

让我们将其应用于您的示例。当您访问参考图像的数据时,您有一个非constQVector,并且您通过operator[]访问数据。这将返回对向量元素的非常量引用。这意味着您可以写入它。你是否真的写信给它并不重要。该对象无法知道您将如何处理引用,因此它必须为潜在的写入做好准备。由于数据(大概(是共享的,因此会触发深层复制。refImage->pixels中的数据被复制到一个新的内存块中,您可以覆盖该内存块,而不会影响那里的任何副本。因此,会消耗更多内存。

如果要在不触发深层复制的情况下完成任务,请将refImage->pixels[i]更改为refImage->pixels.at(i)refImage->pixels.value(i),因为您不检查参考矢量的大小。或者,声明要Image const *refImage,以便使用const QVector使用的operator[]版本;此版本返回常量引用,该引用不会触发深层复制。

改编自我对类似问题的回答。