1110101001
1110101001

Reputation: 5097

Is std::vector preferred over heap arrays for dynamically sized arrays in classes?

If you want to have an array as a member variable of a class there are two main options:

A: Allocate the memory on the heap

class X
{
    int * arr;
public:
    UnionFind(int numNodes)
    {
        arr = new int[numNodes];
    }
}

B: Use a vector

class X
{
    vector <int> arr;
public:
    UnionFind(int numNodes)
    {
        arr.resize(numNodes);
    }
}

Which of these is the preferred method? I know one drawback of heap allocated arrays is that you need to take care of deleting the memory yourself.

As a small side question, if an object of X is created on the heap is vector <int> arr also in the heap within the object? If so, how come vector <int> arr does not manually need to be deleted?

Upvotes: 2

Views: 407

Answers (2)

Tony Delroy
Tony Delroy

Reputation: 106196

You should prefer vector:

  • the vector and vector's elements' destructors are guaranteed to run at the appropriate times

  • things like .push_back are massively easier and more concise to use correctly than coding your own checks on "capacity" and resizing/copy-constructing/moving in a C++ object-aware fashion

  • it's easier to apply algorithms to Standard containers, use the iterators etc.

  • it will be easier to move from vector to another Standard container (list, stack, map, unordered_map, deque etc) if evolving application/library needs suggest it

  • vector has some housekeeping information that's useful: size(), capacity()

  • before C++11 there was a single performance issue compared to using new[] and delete[] - you couldn't do an up-front "sizing" of the vector to hold however-many elements without copy-constructing their values from a prototypical element (constructor "2" here, and resize here) - that meant the constructor or resize had to iterate over every element doing copy construction even if the default constructor was a no-op (e.g. deliberately leaving all members uninitialised)

    • this is very rarely relevant or problematic, and indeed the C++ behaviour was generally safer
  • because it's a proper class, you can (whether you should is another matter) overload operator<<, operator>> for conveniently streaming arbitrary vectors

if an object of X is created on the heap is vector <int> arr also in the heap within the object? If so, how come vector <int> arr does not manually need to be deleted?

Yes, the vector object itself will be embedded within X, so will be on the heap too (similarly, it could be embedded in an automatic/stack variable, a global/namespace/static variable, a thread-specific variable etc.). That said, the vector object contains a pointer which tracks any further memory needed for elements in the vector, and that memory is by default dynamically allocated (i.e. on the heap) regardless of where the vector object itself is held.

Member variables with destructors (such as any vector) have them called automatically by the containing class's destructor.

Upvotes: 2

quantdev
quantdev

Reputation: 23813

When you have the choice between a dynamically allocated C-style array and a std::vector<>, choose the vector.

  • It is safe, does all the alloc/realloc/resizing for you
  • It makes you code more flexible, readable, and easier to maintain
  • It is extremely efficient in most use cases
  • It provides explicit iterators, and plenty of member functions, including size()
  • Many implementations will do index checking in debug mode to catch out-of-bounds errors

Note that std::array exists for most of the cases where a C-array would be preferable (e.g., when allocation on the stack is preferred)

Upvotes: 6

Related Questions