Static Arrays VS. dynamic arrays in c ++ 11

I know that these are very old discussions that have been discussed many times around the world. But at the present time I am having problems choosing the method that I should use, and not the other between static and dynamic arrays in a particular case. Actually, I did not use C ++ 11, I would use static arrays. But now I'm confused, as there may be equivalent advantages between them.

First decision:

template<size_t N> class Foo { private: int array[N]; public: // Some functions } 

The second solution:

 template<size_t N> class Foo { private: int* array; public: // Some functions } 

I can’t get out, because two have their advantages:

  • Static arrays are faster, and we don't care about memory management at all.
  • Dynamic arrays do not affect everything until memory is allocated. After that, they are less convenient to use than static arrays. But since C ++ 11, we can get great benefits from the semantics of movement, which we cannot use with static arrays.

I don’t think there is one good solution, but I would like to get advice or just to find out what you think about all this.

+6
source share
3 answers

I really disagree with "it depends." Never use parameter 2. If you want to use the translation time constant, always use parameter 1 or std :: array. The only advantage that you indicated is that dynamic arrays do not weigh anything before allocation, in fact this is a terrible, huge drawback and one that needs special attention.

Never have objects with more than one phase of construction . Never never. This should be the rule assigned to the memory through a large tattoo. Just never do that.

When you have zombie objects that are not yet completely alive, although not quite dead, the difficulty in managing their life time grows exponentially. You must check each method to see if it is completely alive, or just pretend to be alive. Exception security requires special cases in your destructor. Instead of one simple construction and automatic destruction, you added requirements that should be checked in N different places (# methods + dtor). And the compiler doesn't care if you check. And other engineers will not pass this requirement, so they can configure your code in unsafe ways using variables without checking. And now all these methods have multiple behavior depending on the state of the object, so every user of the object must know what to expect. Zombies will ruin your (encoding) life.

Instead, if you have two different natural lifetimes in your program, use two different objects. But this means that you have two different states in your program, so you must have a state machine, with one state having only one object and another state with both, separated by an asynchronous event. If there is no asynchronous event between two points, if they all fit into the same function area, then the separation is artificial, and you must perform a single-phase construction.

The only case where the size of the translation time should translate into dynamic allocation is when the size is too large for the stack. This then leads to memory optimization, and it should always be evaluated using memory and profiling tools to see which is best. Option 2 will never be the best (it uses a bare pointer - so we lose RAII and any automatic cleaning and control, adding invariants and making the code more complex and easily breaking by others). A vector (as suggested by the bitmask) would be a good first thought, although you may not like the cost of allocating the heap over time. Other options may be static space in the image of your application. But again, they should only be considered after you have determined that you have a memory limit, and what to do next should be determined by real, measurable needs.

+5
source

Do not use. You better use std::vector almost anyway. In other cases, this depends heavily on the reason std::vector will be insufficient and therefore cannot be generally satisfied!

+4
source

I am currently having the problem of deciding which one I should use more than the other in a particular case.

You will need to consider your options in each case in order to determine the optimal solution for a given context - that is, a generalization cannot be made. If one container was ideal for each scenario, the other would be obsolete.

As already mentioned, consider using std implementations before writing your own.

More details:

Fixed length

  • Observe how much you consume.
  • May consume more memory if you think of it as a container with dynamic size.
  • Quick copies.

Variable length

  • Redistributing and resizing can be expensive.
  • May consume more memory than necessary.
  • Fast moves.

A better choice also requires an understanding of the complexity of creating, copying, assigning, etc. types of elements.

And if you use std implementations, remember that implementations may be different.

Finally, you can create a container for these types that abstracts implementation details and dynamically selects the appropriate data item based on size and context β€” abstracting the details behind a common interface. It is also useful to sometimes disable functions or make certain operations (for example, expensive copies) more obvious.

In short, you need to know a lot about types and uses and measure several aspects of your program to determine the optimal container type for a particular scenario.

+4
source

Source: https://habr.com/ru/post/914479/


All Articles