Qt 6: Move QList contents without copying?
-
@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.