EL_9
EL_9

Reputation: 414

Overcoming std::bad_alloc in a constructor without std::nothrow

Let's say I have a class that looks like this:

Class A{
 private:
   int* A1;
   int* A2;
 public:
   A(): A1(new int[1000]), A2(new int[1000]){}         
   ~A(){delete[] A1; delete[] A2;}
}

I want to deal with a situation where the first allocation succeeds and the second fails, and std::bad_alloc is thrown.

From what I gather, the destructor won't be called because the object was not created successfully.

This can be dealt with if I instead do:

 A(): A1(new int[1000]), A2(new(nothrow) int[1000]){} 

Then I will be able to deal with this case without exceptions.

However, from what I read nothrow is very rarely used. I am not sure how exception can be used in this case.

Many thanks.

Upvotes: 0

Views: 130

Answers (1)

HTNW
HTNW

Reputation: 29193

I would use std::unique_ptr.

class A {
    std::unique_ptr<int[]> A1, A2;
public:
    A() : A1(std::make_unique_for_overwrite<int[]>(1000)), A2(std::make_unique_for_overwrite<int[]>(1000)) { }
    // if A1 succeeds and A2 fails, A1 is freed
    // default no-body destructor works fine
};

But if you really want raw pointers, you can squish the logic into a chain of delegating constructors.

class A {
    int *A1, *A2;
    A(int *A1) try : A1(A1), A2(new int[1000]) { }
    catch(...) { delete[] A1; } // handle A2 fails but A1 success; automatically rethrows (note: accessing members in this catch clause is UB, but we have the constructor parameter)
public:
    A() : A(new int[1000]) { }
    // any exception in first allocation is immediately thrown here
    // any exception in second allocation bubbles up through here after being rethrown
    ~A() { delete[] A1; delete[] A2; }
};

Upvotes: 1

Related Questions