Tracer
Tracer

Reputation: 2736

Smart pointers inside classes?

I'm having a following example of class template:

template<class T>
class MyContainer{
public:
    T* myArray;
    int size;
    MyContainer(int n) : size(n){
        myArray = new T[n];
    }
    ~MyContainer(){
        delete[] myArray;
    }
};

Is it possible to use smart pointers like unique_ptr or shared_ptr for myArray so I don't need to deallocate it in destructor? How?

Upvotes: 0

Views: 416

Answers (3)

Max Lybbert
Max Lybbert

Reputation: 20041

Not only can you, but you really should. Programmers are often surprised to discover that if a constructor throws an exception (which is the recommended way to signal that an object can't be created for any reason), the destructor is not run, because there's no general way for the compiler to know which lines in the destructor correspond to which lines in the constructor.

On the other hand, any objects that have been created are destroyed because there is a general way to know which ones need to be destroyed. To put it another way, if your object had two raw pointers, and the first call to new succeeded, but the second failed, the destructor wouldn't be run, and the first pointer would never be deleted. But if your object had two smart pointers, and the first was constructed successfully and the second failed, the first smart pointer would be properly destroyed and you wouldn't have to worry about it.

Upvotes: 1

quantdev
quantdev

Reputation: 23793

Yes you can, and you really should :

template<class T>
class MyContainer{
public:
    std::unique_ptr<T[]> myArray;
    int size;
    MyContainer(int n) : myArray(new T[n]), size(n) { }
};

int main() {
  MyContainer<int> c(10);
}

Or if possible, pass the size as a template parameter :

template<class T, std::size_t N>
class MyContainer{
public:
    std::unique_ptr<T[]> myArray;
    int size = N;
    MyContainer() : myArray(new T[N]) { }
};

int main() {
  MyContainer<int, 10> c;
}

Or, if possible, just use std::vector<> or std::array<>

Notes:

  • Variable lengths arrays are non standard.
  • You should initialize class members in their order of declaration.
  • The size should be an unsigned (std::size_t)

Upvotes: 4

Deduplicator
Deduplicator

Reputation: 45654

template<class T>
class MyContainer{
public:
    unique_ptr<T[]> myArray;
    int size;
    MyContainer(int n) : size(n), myArray(new T[n]) {}
};

The smart-pointer must use the array deallocator, otherwise it's UB, though in the case of trivial types probably the same code.

Take a look here for the whole std::unique_ptr interface.

Upvotes: 2

Related Questions