Ravi
Ravi

Reputation: 11

Delete a vector without deleting the array

I'm trying to populate a vector of doubles in C++ and pass the associated array to Fortran. But I'm having trouble freeing the rest of the memory associated with the vector. I'd like to avoid copying. Here's what I have:

std::vector<double> *vec = new std::vector<double>();
(*vec).push_back(1.0);
(*vec).push_back(2.0);
*arr = (*vec).data();            //arr goes to Fortran

How do I delete vec while keeping arr intact? Is there a way to nullify the pointer to arr in vec so that I can then delete vec?

Update

I see that I didn't give enough information here. A couple things:

  1. I'm actually calling a C++ function in Fortran using iso_c_binding
  2. I don't know how large the vec needs to be. The vector class looks good for this situation

I might try Guillaume's suggestion eventually, but for now, I'm passing vec to the Fortran and calling another C++ function to delete it once I'm done with the data

Upvotes: 0

Views: 625

Answers (4)

R Sahu
R Sahu

Reputation: 206607

How do I delete vec while keeping arr intact? Is there a way to nullify the pointer to arr in vec so that I can then delete vec?

The library does not provide any built-in capability to do that. You have to do the bookkeeping work yourself.

  1. Allocate memory for the data and copy data from the vector.
  2. Send the data to FORTRAN.
  3. Decide when it is safe to deallocate the data and then delete them.

// Fill up data in vec
std::vector<double> vec;
vec.push_back(1.0);
vec.push_back(2.0);

// Allocate memory for arr and copy the data from vec
double* arr = new double[vec.size()];
std::copy(vec.begin(), vec.end(), arr);

// use arr

// delete arr
delete [] arr;

Upvotes: 1

Xirema
Xirema

Reputation: 20396

You need to rethink your program design.

Somehow, somewhere, you need to keep an array alive while Fortran is using it. So whatever context you're using to access Fortran should probably be responsible for ownership of this array.

class fortran_context {
    /*Blah blah blah whatever API you're using to access Fortran*/
    void * arr;
    std::vector<double> vec; //Don't allocate this as a pointer; makes no sense!
public:
    fortran_context() {
        arr = //Do whatever is necessary to setup Fortran stuff. I'm assuming your
        //api has some kind of "get_array_pointer" function that you'll use.
    }

    ~fortran_context() {
        //Do the cleanup for the fortran stuff
    }

    //If you want to spend time figuring out a robust copy constructor, you may.
    //Personally, I suspect it's better to just delete it, and make this object non-copyable.
    fortran_context(fortran_context const&) = delete;

    std::vector<double> & get_vector() {
        return vec;
    }

    std::vector<double> const& get_vector() const {
        return vec;
    }

    void assign_vector_to_array() {
        *arr = vec.data();
    }

    void do_stuff_with_fortran() {
        assign_vector_to_array();
        //???
    }
};

int main() {
    fortran_context context;
    auto & vec = context.get_vector();
    vec.push_back(1.0);
    vec.push_back(2.0);
    context.do_stuff_with_fortran();
    return 0;
} //Cleanup happens automatically due to correct implementation of ~fortran_context()

I've abstracted a lot of this because I don't know what API you're using to access Fortran, and I don't know what kind of work you're doing with this array. But this is, by far, the safest way to ensure that

  • The vector's allocated memory exists so long as you are doing stuff in Fortran
  • The memory associated with the vector will be cleaned up properly when you're done.

Upvotes: 3

Guillaume Racicot
Guillaume Racicot

Reputation: 41780

How do I delete vec while keeping arr intact? Is there a way to nullify the pointer to arr in vec so that I can then delete vec?

You don't.


I think you misuse or misunderstood what vector is for. It is not meant to expose memory management of the underlying array, but to represent a dynamically sized array as a regular type.

If you need to explicitly manage memory, I'd suggest you to use std::unique_ptr<T[]>. Since unique pointers offers a way to manage memory and to release it's resource without deleting it, I think it's a good candidate to meet your needs.

auto arr = std::make_unique<double[]>(2);
arr[0] = 1.;
arr[1] = 2.;
auto data = arr.release();

// You have to manage `data` memory manually,
// since the unique pointer released it's resource.

// arr is null here
// data is a pointer to an array, must be deleted manually later.

delete[] data;

Upvotes: -1

Christopher Pisz
Christopher Pisz

Reputation: 4010

What you are asking for is not possible. std::vector, being a well behaved template class will release the internals that it owns and manages when it is destroyed.

You will have to keep vector alive while you are using its contents, which makes perfect sense. Otherwise, you will have to make a copy.

Also, I don't see why you are allocating the vector on the heap, it doesn't seem needed at all.

Upvotes: 0

Related Questions