I'm trying to make a deep copy of a QList, I'm using Qt 4.8. In the code below mData
is a QList<unsigned char>
member variable of the Test
class.
In first instance I thought the code below should work, however diving deeper in Qt's implicitly shared (i.e. copy-on-write) concept, I'm doubting if this is the correct way to go.
Test::Test(QList<unsigned char> &aData) {
mData.QList(aData);
}
According Qt,
QList::QList(const QList & other)
Constructs a copy of other.
This operation takes constant time, because QList is implicitly shared. This makes returning a QList from a function very fast. If a shared instance is modified, it will be copied (copy-on-write), and that takes linear time.
I want to ensure that if aData
goes out of scope or if the content of aData
is modified, this doesn't change the content of mData
. Is this possible without having to iterate and copy each list entry separately?
Note: this is not a duplicate of Qt 4.5 - QList::QList(const QList&) - is this a deep copy constructor? because this question implicitly asks how to create a deep copy" instead of if something is a deep copy.
The implicit copy mechanism of Qt will automatically create a deep copy of a QList
if this is required.
QList<int> a;
a.append(1);
a.append(2);
Now we have a list a
with two values.
QList<int> b = a;
// a = 1, 2
// b = 1, 2
The copy of b
is the same as a
. The two list share the same data, so the copy operation needs almost no time, but b
is marked internally as a copy.
b.append(3);
// a = 1, 2
// b = 1, 2, 3
Another example:
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
As soon you change something on b, an implicit deep copy is made. It does not matter how the copied list is modified, it works on any method.
If you are using references, there is no deep copy made automatically:
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
To enforce a deep-copy, just make a copy of the list inside of the function. But of course, better just pass the argument as copy instead as reference, this simplifies the code.
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
So actually, you can use a QList and any other Qt container similar to a primitive data type like int
or like QString
. The implicit copy is automatically done in the "background".
So your example should just use a simple copy:
class Test {
QList<int> _m;
public:
Test(QList<int> m) : _m(m) {
}
}
The class Test
automatically creates a deep-copy of the parameter m
. Because of the implicit copy mechanism, use a copy of the parameter m
is not much slower than use a reference. The deep copy is automatically done at the first modification of the list.
If you would like to use a reference, use a const reference:
class Test {
QList<int> _m;
public:
Test(const QList<int> &m) : _m(m) {
}
}
This will create an implicit deep-copy as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With