如何创建QList的深层副本(Qt 4.8)

时间:2015-05-18 15:36:33

标签: c++ qt

我正在尝试制作QList的深层副本,我正在使用Qt 4.8。在下面的代码中,mDataQList<unsigned char>类的Test成员变量。

在第一个例子中,我认为下面的代码应该可行,但是在Qt的隐式共享(即写时复制)概念中深入探讨,我怀疑这是否是正确的方法。

Test::Test(QList<unsigned char> &aData) {
    mData.QList(aData);
}

根据Qt,

  

QList :: QList(const QList&amp; other)

     

构造其他的副本。

     

此操作需要恒定时间,因为QList是隐式的   共享。这使得从函数返回QList的速度非常快。如果一个   共享实例被修改,它将被复制(copy-on-write),和   需要线性时间。

我想确保如果aData超出范围或aData的内容被修改,则不会更改mData的内容。这是否可以,而不必分别迭代和复制每个列表条目?

注意:这不是Qt 4.5 - QList::QList(const QList&) - is this a deep copy constructor?的重复,因为此问题隐含地要求如何创建深层副本“而不是如果某些内容是深层副本

1 个答案:

答案 0 :(得分:5)

如果需要,Qt的隐式复制机制将自动创建QList的深层副本。

QList<int> a;
a.append(1);
a.append(2);

现在我们有一个包含两个值的列表a

QList<int> b = a;
// a = 1, 2
// b = 1, 2

b的副本与a相同。这两个列表共享相同的数据,因此复制操作几乎不需要时间,但b在内部标记为副本。

b.append(3);
// a = 1, 2
// b = 1, 2, 3

另一个例子:

QList<int> a;
a << 1 << 2 << 3;
// a = 1, 2, 3
QList<int> b = a;
// a = 1, 2, 3; b = 1, 2, 3
b[0] = 7;
// a = 1, 2, 3; b = 7, 2, 3

一旦你在b上改变某些东西,就会产生隐式深层复制。复制列表的修改方式无关紧要,它适用于任何方法。

如果您使用的是引用,则不会自动进行深层复制:

void addElement(QList<int> &x, int e) {
    x.append(e);
}

QList<int> a;
a.append(1);
a.append(2);
addElement(a, 3);
// a = 1, 2, 3

要强制执行深层复制,只需复制函数内的列表。但是,当然,最好只将参数作为副本传递给参考,这样可以简化代码。

void printListPlus1(QList<int> &x) {
    QList<int> xCopy = x; 
    xCopy.append(1);
    // print the list
}

QList<int> a;
a << 1 << 2;
// a = 1, 2
printListPlus1(a);
// a = 1, 2

实际上,您可以使用QList和任何其他Qt容器,类似于原始数据类型,如int或类似QString。隐式副本在&#34;背景&#34;。

中自动完成

您的示例

所以你的例子应该只使用一个简单的副本:

class Test {
    QList<int> _m;
public:
    Test(QList<int> m) : _m(m) {
    }    
}

班级Test会自动创建参数m的深层副本。由于隐式复制机制,使用参数m的副本并不比使用引用慢得多。深度复制在列表的第一次修改时自动完成。

如果您想使用引用,请使用const引用:

class Test {
    QList<int> _m;
public:
    Test(const QList<int> &m) : _m(m) {
    }    
}

这也会创建隐式深层复制。