1

I was watching a youtube video on how to implement your own vector/dynamic_array in C++. I understood everything except one like of code, I'm new to c++ and trying to understand the underline data structure implementation. But I didn't see such a line of code like that one. The Code:

template<typename... Args>
T& EmplaceBack(Args&&... args) {
    if (m_Size >= m_Capacity) {
        ReAlloc(m_Capacity + m_Capacity / 2);
    }
    new(&m_Data[m_Size])T(std::forward<Args>(args)...); 
    return m_Data[m_Size++];
}

The line I didn't understand:

new(&m_Data[m_Size])T(std::forward<Args>(args)...);

What that line of code is really doing ? Btw, I don't really know what std::forward is. Thx for any explanation. :)

AM Z
  • 423
  • 2
  • 9
  • 4
    This use of `new` is called *placement-new*, look it up. As for `std::forward`, look up perfect forwarding. – HolyBlackCat Aug 23 '20 at 12:50
  • 1
    You will find it much easier to actually learn and understand C++ [from a good C++ textbook](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) than from some random Youtube video, which any clown can make and upload. Everything you mentioned is explained in the textbook, in organized, logical order. Otherwise, as is the case here, you are faced with many different concepts (placement new, perfect forwarding) from completely different areas of knowledge in C++, and you have no idea whatsoever how all of that works, without having learned it, in an organized way. – Sam Varshavchik Aug 23 '20 at 13:05

1 Answers1

3

This line of code constructs an object of type T with arguments args... at the address &m_Data[m_Size]. No memory allocation involved.

new(&m_Data[m_Size])T(std::forward<Args>(args)...);

Lets assume we call a "normal" new operator:

new T((std::forward<Args>(args)...);

This will allocate memory which size will be equal to sizeof(T) and call a constructor of type T at that memory address. std::forward is used in the technique called perfect forwarding. In short: no copies, no moves, no passing in any way - arguments are just given to the constructor as if you called it directly.

But what if you have your memory already preallocated - the main performance boosting point of many containers, like the vector? Placement new operator is your friend here. You provide it with the address of the preallocated memory and it only constructs the object. And no delete is required later, because you didn't allocate anything with placement new!

What about the destruction? Normally destructors are called automatically when you delete the object. In this case you'll have to call the object's destructor directly, like this - t->~T();

Vasilij
  • 1,861
  • 1
  • 5
  • 9
  • Any one know what the letter 'm' in m_data or m_size stands for? Why that name is used everywhere :D – Rango Jul 19 '23 at 13:44