Basic myVector class raw vs smart pointer I'm writing a myVector class for a class I'm taking.  I don't believe I'm "strong" with smart pointers right now, so that's my question.  This is just an excerpt from a much larger class that I've completed.

Is there a way to use the shared pointer and dynamically allocate the size, so that I can use the [] notation with that pointer?  I've been looking on Stack Overflow and don't see anything referencing this particular usage.  My next question/conclusion would then be that it's best to stick with raw pointers in the case where I want to use array notation.

#include &lt;iostream&gt;
//#include &lt;memory&gt;

class myVector
{
private:
    int sz;
    int * array;

public:
    myVector(int a, int b)
    {
        sz = a;
        array = new int[sz];
        for(int i(0); i &lt; sz; ++i)
            array[i] = b;
    }
    ~myVector(){ delete [] array; };
    int size() const
    {
        return sz;
    }
    int &amp;operator[](const int num)
    {
        return array[num];
    }
};

int main()
{
    myVector testing(10, 6);
    for(int i(0); i &lt; testing.size(); ++i)
    {
        testing[i] = testing[i] * i;
        std::cout &lt;&lt; testing[i] &lt;&lt; std::endl;
    }
    return 0;
}
In the following, I tried to collect the options you have for your custom vector class, and summarize their pros and cons. But before that I'd suggest to use generic programming when you write your vector class, i.e.

template&lt;typename T&gt;
class myVector
{
     size_t sz;
     T* array;

     //all the rest
};


Note two things here: Instead of the int *, I've wrote T*, where T is the type you specify in the program via myVector&lt;int&gt;, say. This you can hold elements of arbitrary type and you do not need to copy the whole class once you need a double type.

Further, I've used the type size_t for the size of the vector, which is the type often used in C++ to denote sizes of objects (in fact, it's just a large unsigned int type).



Choosing the right storage type:


First, and most naturally, you can use an STL container inside, preferably std::vector: this is one example of the RAII way to do it, which basically means that you usually don't have to care for the memory management by yourself. Although from the first it sounds a bit redundant to include a std::vector in your custom vector class, it actually can be rather useful, for instance when you want to add arithmetics to your vector.

template&lt;typename T&gt;
class myVector
{
     std::vector&lt;T&gt; array;
};


This has several advantages: visibly, you don't need a variable sz anymore, as the std::vector already manages the size. Next -- and this is an important thing -- as your array becomes correctly copied, moved, assigned and destructed, your class will perform these operations correctly as well.

In the following, let us consider the copy operation as an example: in the above approach, when one copies the class, the new class contains a copy of the original std::vector.
Using a raw pointer as in your OP. This is nowadays a discouraged way to do it, just because you have to manually care for the memory management. Once you invoke array = new int[sz], array is a pointer to some allocated memory on the heap, i.e. it's so to say something outside of the class, and the class itself must take care that this memory is correctly released for further usage when it is destructed. Thus you need to write a destructor, and therefore -- according to the rule of three(five) -- also copy constructors, assignment operators (, move constructors).

Consider again the copy process. The copied myVector just copies the raw pointer, such that now two pointers point to the same memory region. However, these two pointers don't know about each other. So, it becomes a hard task to prevent one of the classes to delete the memory when it goes out of scope, as then the other class will become a dangling pointer: it points to a destructed and thus invalid object. In order to avoid this, you'd need to count how many pointers point to a given object, and call the delete only if the last pointer goes out of scope (i.e. when nobody needs the object anymore).
Shared pointers exactly do this: they count how many pointers point to a given object which has been allocated on the heap.

template&lt;typename T&gt;
class myVector
{
     std::shared_ptr&lt;T&gt; array;
     // construct via array= std::make_shared( new T[sz], std::default_delete&lt;T[]&gt;() );
     // this is necessary so that "delete[]" is called, an not "delete".

     //or better
     std::shared_ptr&lt;std::vector&lt;T&gt; &gt; array;
};


By using them, you get almost the same behaviour as by using a raw pointer but have a lot of advantages. Most importantly, you again are on the RAII track, you don't need to care for all the default functions and let the compiler generate them. A disadvantage is that a shared_ptr is usually less performant than a raw pointer, but this is often taken into account in favor of a correct code.

Regarding the example, copying works fine: the newly copied class only contains the pointer to the object and not the object itself, which is an advantage when the arrays are large and do not need to be changed in the copy. In the copy process, the shared_ptr increases its so-called reference count, such that it knows when exactly to call delete.
Finally, there is another smart pointer, namely std::unique_ptr. It addresses the above problem in a completely different way: it simply doesn't allow copying, so that there is always one pointer which does the memory management. It's also said that the unique_ptr owns the object. Other, non-owning pointers are allowed, but these should never do any memory-related operations (--never call delete).

It is possible to use it here and it could also be reasonable, but be aware that your class won't possess automatically generated copy and assignment operators. This is probably not intended.




Summary: as written above, I'd use the std::vector&lt;T&gt; alternative, and depart from it only for a good reason. Only then, I'd use the shared_ptr alternative. I would never use the raw pointer array.