Qt 6: Move QList contents without copying?
-
@JonB
QList
does have an append overload for moving:void QList::append(QList<T> &&value)
This is an overloaded function.
Moves the items of the value list to the end of this list.
This function was introduced in Qt 6.0.Technically, it should not copy but rather move and append the value from the passed
list
tofullList
. Why is this not doing that?@CJha
I don't know since I have never used Qt 6.Depends what you/they mean by "move" versus "copy". I stick by my claim/understanding that since
QList
elements are now contiguous like an array/vector it must "copy" the elements to the destination list to make it so. The only difference is that it could invalidate the passed-in source list.I do not know how
QList<T>
might work withstd::move()
. I do not know whether it might leavelist
in an "unspecified state". Did you try, say,fullList.append(list);
just to seen what happens tolist
after this case?This is the limit of my knowledge/guesswork! You probably need a QT +
std
expert to help you further :) -
@CJha
I don't know since I have never used Qt 6.Depends what you/they mean by "move" versus "copy". I stick by my claim/understanding that since
QList
elements are now contiguous like an array/vector it must "copy" the elements to the destination list to make it so. The only difference is that it could invalidate the passed-in source list.I do not know how
QList<T>
might work withstd::move()
. I do not know whether it might leavelist
in an "unspecified state". Did you try, say,fullList.append(list);
just to seen what happens tolist
after this case?This is the limit of my knowledge/guesswork! You probably need a QT +
std
expert to help you further :)@JonB No it does not have to copy if using std::move. As far as I know Qt container use heap allocated memory with a pointer for the actual data. Then using std::move it is enough to assign the pointer to the data in the destination container and set it to nullptr in the source container.
-
@CJha
I don't know since I have never used Qt 6.Depends what you/they mean by "move" versus "copy". I stick by my claim/understanding that since
QList
elements are now contiguous like an array/vector it must "copy" the elements to the destination list to make it so. The only difference is that it could invalidate the passed-in source list.I do not know how
QList<T>
might work withstd::move()
. I do not know whether it might leavelist
in an "unspecified state". Did you try, say,fullList.append(list);
just to seen what happens tolist
after this case?This is the limit of my knowledge/guesswork! You probably need a QT +
std
expert to help you further :)@JonB Thanks. Yes, I did try multiple cases, here are few important ones
fullList.append(list); // copies and appends the data from list to fullList but list itself is not changed fullList.append(std::move(list)); // same as above fullList = std::move(list); // moves the data from list to fullList, the list is empty but in defined state after this move
It seems that it is only moving the data from
list
tofullList
when the data is being assigned using= std::move()
in all other cases it leaves the data inlist
as it was. -
@JonB No it does not have to copy if using std::move. As far as I know Qt container use heap allocated memory with a pointer for the actual data. Then using std::move it is enough to assign the pointer to the data in the destination container and set it to nullptr in the source container.
@jsulm said in Qt 6: Move QList contents without copying?:
@JonB No it does not have to copy if using std::move. As far as I know Qt container use heap allocated memory with a pointer for the actual data. Then using std::move it is enough to assign the pointer to the data in the destination container and set it to nullptr in the source container.
Have you read what I wrote above about Qt6 and contiguous element allocation? What you write would indeed be the case for
QList::QList(const QList<T> &other)
constructor. However the user is asking aboutQList::append(QList<T> &&value)
method introduced at Qt 6.0, that's the whole point. Could you explain how it could append a list to an existing list without having to copy the elements onto the existing list while still maintaining contiguous memory like an array/vector? I welcome your input :) -
@jsulm said in Qt 6: Move QList contents without copying?:
@JonB No it does not have to copy if using std::move. As far as I know Qt container use heap allocated memory with a pointer for the actual data. Then using std::move it is enough to assign the pointer to the data in the destination container and set it to nullptr in the source container.
Have you read what I wrote above about Qt6 and contiguous element allocation? What you write would indeed be the case for
QList::QList(const QList<T> &other)
constructor. However the user is asking aboutQList::append(QList<T> &&value)
method introduced at Qt 6.0, that's the whole point. Could you explain how it could append a list to an existing list without having to copy the elements onto the existing list while still maintaining contiguous memory like an array/vector? I welcome your input :) -
@jsulm said in Qt 6: Move QList contents without copying?:
@JonB No it does not have to copy if using std::move. As far as I know Qt container use heap allocated memory with a pointer for the actual data. Then using std::move it is enough to assign the pointer to the data in the destination container and set it to nullptr in the source container.
Have you read what I wrote above about Qt6 and contiguous element allocation? What you write would indeed be the case for
QList::QList(const QList<T> &other)
constructor. However the user is asking aboutQList::append(QList<T> &&value)
method introduced at Qt 6.0, that's the whole point. Could you explain how it could append a list to an existing list without having to copy the elements onto the existing list while still maintaining contiguous memory like an array/vector? I welcome your input :)@JonB said in Qt 6: Move QList contents without copying?:
Could you explain how it could append a list to an existing list without having to copy the elements onto the existing list while still maintaining contiguous memory like an array/vector? I welcome your input :)
It moves the data from memory a to memory b. It's just not a copy but a move operation. Nothing more.
void addList(QList<T>& list) { fullList.append(std::move(list)); }
How should this be moved at all when
list
is a const ref? You can move a const object... -
@JonB said in Qt 6: Move QList contents without copying?:
Could you explain how it could append a list to an existing list without having to copy the elements onto the existing list while still maintaining contiguous memory like an array/vector? I welcome your input :)
It moves the data from memory a to memory b. It's just not a copy but a move operation. Nothing more.
void addList(QList<T>& list) { fullList.append(std::move(list)); }
How should this be moved at all when
list
is a const ref? You can move a const object...@Christian-Ehrlicher said in Qt 6: Move QList contents without copying?:
It moves the data from memory a to memory b. It's just not a copy but a move operation. Nothing more.
For this purpose I am calling that "copy" because (does it not?) have to copy the elements (in the
QList
, not what they might point to) from memory area a to area b? Certainly if iterates that is O(n), I don't know whether you mean CPUs have an instruction to do that fast instead? Think about if it appends a list of 1,000,000 items to an existing list of one item. Moving and appending a list (like a linked list) could be made an O(1) operation, but not with the vector implementation of Qt6QList
, that is my point. I think of "copy" for O(n), "move" to me implies O(1) (hopefully). Is this not correct? -
@Christian-Ehrlicher said in Qt 6: Move QList contents without copying?:
It moves the data from memory a to memory b. It's just not a copy but a move operation. Nothing more.
For this purpose I am calling that "copy" because (does it not?) have to copy the elements (in the
QList
, not what they might point to) from memory area a to area b? Certainly if iterates that is O(n), I don't know whether you mean CPUs have an instruction to do that fast instead? Think about if it appends a list of 1,000,000 items to an existing list of one item. Moving and appending a list (like a linked list) could be made an O(1) operation, but not with the vector implementation of Qt6QList
, that is my point. I think of "copy" for O(n), "move" to me implies O(1) (hopefully). Is this not correct?@JonB Don't look on the QList but it's contents. The content is moved but not copied - so the move ctor is called and not the copy ctor.
-
@JonB Don't look on the QList but it's contents. The content is moved but not copied - so the move ctor is called and not the copy ctor.
@Christian-Ehrlicher said in Qt 6: Move QList contents without copying?:
so the move ctor is called and not the copy ctor.
I never suggested otherwise. My question/answer at least is based on my assumption that the implementation in move constructor will be O(n) and not O(1) at Qt6
QList
which requires contiguous memory. Which is what I would care about (at least as part of the whole) if I were asking the OP's question. -
@Christian-Ehrlicher said in Qt 6: Move QList contents without copying?:
so the move ctor is called and not the copy ctor.
I never suggested otherwise. My question/answer at least is based on my assumption that the implementation in move constructor will be O(n) and not O(1) at Qt6
QList
which requires contiguous memory. Which is what I would care about (at least as part of the whole) if I were asking the OP's question.@JonB said in Qt 6: Move QList contents without copying?:
Which is what I would care about (at least as part of the whole) if I were asking the OP's question.
But even then a move would be faster than (or equal if QList contains a pod) a copy. But the complexity stays, yes. But as I said - it can't work the way it is written. -
@JonB said in Qt 6: Move QList contents without copying?:
Could you explain how it could append a list to an existing list without having to copy the elements onto the existing list while still maintaining contiguous memory like an array/vector? I welcome your input :)
It moves the data from memory a to memory b. It's just not a copy but a move operation. Nothing more.
void addList(QList<T>& list) { fullList.append(std::move(list)); }
How should this be moved at all when
list
is a const ref? You can move a const object...@Christian-Ehrlicher said in Qt 6: Move QList contents without copying?:
But the complexity stays, yes.
OK.
@Christian-Ehrlicher said in Qt 6: Move QList contents without copying?:
How should this be moved at all when list is a const ref? You can move a const object...
@Christian-Ehrlicher said in Qt 6: Move QList contents without copying?:
But as I said - it can't work the way it is written.
Sorry, don't know about others but I'm not understanding where " list is a const ref" here, where is the
const
? Please be gentle in your answer ;-)
[Also, did you mean "You can move a const object..." or did you mean "can't"?] -
@Christian-Ehrlicher said in Qt 6: Move QList contents without copying?:
But the complexity stays, yes.
OK.
@Christian-Ehrlicher said in Qt 6: Move QList contents without copying?:
How should this be moved at all when list is a const ref? You can move a const object...
@Christian-Ehrlicher said in Qt 6: Move QList contents without copying?:
But as I said - it can't work the way it is written.
Sorry, don't know about others but I'm not understanding where " list is a const ref" here, where is the
const
? Please be gentle in your answer ;-)
[Also, did you mean "You can move a const object..." or did you mean "can't"?]@JonB said in Qt 6: Move QList contents without copying?:
list is a const ref" here, where is the const? Please be gentle in your answer ;-)
void addList(QList<T>& list) { fullList.append(std::move(list)); }
list is const - so nothing to move here. -
@JonB said in Qt 6: Move QList contents without copying?:
list is a const ref" here, where is the const? Please be gentle in your answer ;-)
void addList(QList<T>& list) { fullList.append(std::move(list)); }
list is const - so nothing to move here.Here I somehow was in the wrong path... sorry for the noise:
class CopyMoveTest { public: CopyMoveTest() { std::cout << "CopyMoveTest: plain ctor\n"; } CopyMoveTest(const CopyMoveTest &) { std::cout << "CopyMoveTest: copy ctor\n"; } CopyMoveTest(CopyMoveTest &&) { std::cout << "CopyMoveTest: move ctor\n"; } CopyMoveTest operator=(const CopyMoveTest &) { std::cout << "CopyMoveTest: copy operator\n"; return *this; } CopyMoveTest operator=(const CopyMoveTest &&) { std::cout << "CopyMoveTest: move operator\n"; return *this; } }; void refCopy(CopyMoveTest &in) { CopyMoveTest c(in); } void rValueRefCopy(CopyMoveTest &&in) { CopyMoveTest c(in); } void refMove(CopyMoveTest &in) { CopyMoveTest c(std::move(in)); } void rValueRefMove(CopyMoveTest &&in) { CopyMoveTest c(std::move(in)); } int main(int , char **) { CopyMoveTest a; std::cout << "\nref source copy\n"; refCopy(a); std::cout << "\nref source move\n"; refMove(a); std::cout << "\nrvalue ref source copy\n"; rValueRefCopy(std::move(a)); std::cout << "\nrvalue ref source move\n"; rValueRefMove(std::move(a)); } --> CopyMoveTest: plain ctor ref source copy CopyMoveTest: copy ctor ref source move CopyMoveTest: move ctor rvalue ref source copy CopyMoveTest: copy ctor rvalue ref source move CopyMoveTest: move ctor
-
@Christian-Ehrlicher said in Qt 6: Move QList contents without copying?:
It moves the data from memory a to memory b. It's just not a copy but a move operation. Nothing more.
For this purpose I am calling that "copy" because (does it not?) have to copy the elements (in the
QList
, not what they might point to) from memory area a to area b? Certainly if iterates that is O(n), I don't know whether you mean CPUs have an instruction to do that fast instead? Think about if it appends a list of 1,000,000 items to an existing list of one item. Moving and appending a list (like a linked list) could be made an O(1) operation, but not with the vector implementation of Qt6QList
, that is my point. I think of "copy" for O(n), "move" to me implies O(1) (hopefully). Is this not correct?@JonB said in Qt 6: Move QList contents without copying?:
Think about if it appends a list of 1,000,000 items to an existing list of one item. Moving and appending a list (like a linked list) could be made an O(1) operation
Well, you are right about that. However, I would expect that something would be done with the data afterwards. Iterating over the elements of a linked list and the elements of a vector is both O(n). Still, in the general case a vector will be faster because of consecutive memory whereas a list might have many cache misses. If iteration is done more than once the vector might be faster (after copying 1,000,000 items). It is a very tricky problem.