如何创建QList(Qt 4.8)的深拷贝

5
我正在尝试制作一个QList的深拷贝,我正在使用Qt 4.8。在下面的代码中,mDataTest类的QList<unsigned char>成员变量。
起初,我认为下面的代码应该可以工作,但是深入研究Qt的隐式共享(即写时复制)概念后,我开始怀疑这是否是正确的方法。
Test::Test(QList<unsigned char> &aData) {
    mData.QList(aData);
}

根据Qt,
QList::QList(const QList & other)
构造一个other的副本。
这个操作花费恒定时间,因为QList是隐式共享的。这使得从函数返回QList非常快。如果修改了共享实例,它将被复制(写时复制),这需要线性时间。
我希望确保如果aData超出范围或者aData的内容被修改,这不会改变mData的内容。是否有可能在不必逐个迭代和复制每个列表条目的情况下实现这一点?
注意:这不是Qt 4.5 - QList::QList(const QList&) - is this a deep copy constructor? 的重复,因为这个问题间接地询问“如何”创建深层副本,而不是“是否”是深层副本。

我在怀疑这是否是正确的方法 - 你试过了吗?请注意容器具有写时复制的概念,这意味着如果您创建一个副本并更改源容器,则该副本将保留原始内容,而不会更改源所做出的修改。 - TheDarkKnight
1
这不是重复的,请看我在问题底部添加的注释。 - Gio
1个回答

9
Qt的隐式复制机制会在需要时自动创建一个QList的深层副本。
QList<int> a;
a.append(1);
a.append(2);

现在我们有一个包含两个值的列表a
QList<int> b = a;
// a = 1, 2
// b = 1, 2
< p > 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和其他类似于原始数据类型(如intQString)的Qt容器。隐式复制会自动在“后台”执行。

示例

因此,您的示例应该只使用简单的复制:

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

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

如果您想使用引用,请使用常量引用:

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接