D9236: Fill lists of default-constructed types directly, not append any by value

Aaron Puchert noreply at phabricator.kde.org
Sat Dec 9 20:48:37 UTC 2017


aaronpuchert added a comment.


  In https://phabricator.kde.org/D9236#177787, @kossebau wrote:
  
  > I still have to complete my C++11 classes sadly. In my naive mind I would have hoped something like this would be possible, in general:
  >
  >   alloc heap memory for list items
  >   for each item
  >       default constructor item on heap
  >       setup item on heap
  >
  >
  > I would not see any principal need to prepare the item on the stack. Is there? Why would C++11 still prefer a move operator, instead of going directly for the final memory destination?
  
  
  You are completely right, I would just advise against going through the vector twice, as you'd do with `resize()`. So if you still use `reserve()`, then add single elements and initialize them that's fine.
  
  > With QVector it seems there is some practical need for a separate item instance only because the API does not have any hooks for some iterator-based filling, any item construction is hardcoded to the default constructor (Edit: besides the `append()` logic which does copy/move constructor, which though does not gain us something for avoiding the temp copy on the stack). One could imagine some `fill(int count, functor constructor)` or some `T& appendNew()`. But it isn't there after all the years, despite list filling from a loop surely being a common need. Would that be an anti-pattern for some reason?
  
  STL's `std::vector` has emplace_back <http://en.cppreference.com/w/cpp/container/vector/emplace_back> that constructs a new vector element in place. Sadly `QVector` doesn't have it yet, and I've seen Qt developers express their doubts <https://stackoverflow.com/a/5863014> it's going to happen soon.
  
  What I was trying to say is that compilers have a lot of freedom with local variables - they might not ever be written to actual memory, sometimes not even into registers. The only requirement imposed is that the observed behavior is not allowed to change. This is why debugging optimized code can be so hard. Eliminating copies of local variables may not actually improve performance.
  
  But even if the compiler is not able to optimize out copies, all that stuff is still happening in the L1 cache. Drastic performance degradation usually happens when there is too much data and stuff gets evicted to main memory. Hence it's preferable to do everything in one pass.
  
  > No real clue yet about move operators, but how does it spare us here any constructor and deconstructor calls? And with the QType-sub-datastructures being implicitly-shared usually, does the move operator make a difference when it comes to unneeded temporary allocations?
  
  The benefit for implicitly-shared data types might be small, but I think not all types are. So maybe I should clarify that moves might not always be cheaper than copies (for simple data types they do the same), but sometimes there is a considerable benefit, usually when types own (meaning it's not shared) a chunk of data on the heap.
  
  In https://phabricator.kde.org/D9236#177745, @aaronpuchert wrote:
  
  > By the way, it's usually a good idea to have vector elements nothrow-move constructible. This can be checked with
  >
  >   static_assert(std::is_nothrow_move_constructible<Type>::value, "...");
  >
  >
  > for a `QVector<T>`. This doesn't always seem to be the case. Maybe I'll have a look what can be done there.
  
  
  Well <https://stackoverflow.com/a/5863014>, "QVector still doesn't move elements on reallocations."

REPOSITORY
  R32 KDevelop

REVISION DETAIL
  https://phabricator.kde.org/D9236

To: kossebau, #kdevelop
Cc: aaronpuchert, brauch, kdevelop-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kdevelop-devel/attachments/20171209/3cbb6207/attachment.html>


More information about the KDevelop-devel mailing list