Deleting dereferenced elements from vector

2019-09-08 06:55发布

问题:

I have created objects by using new, but then have dereferenced them before adding them to a vector. Despite trawling the internet I cannot work out how I can call delete on these items. I want to do this just using standard C++ and STL I don't want (e.g.) to use Boost libraries.

As you can see a, b and c lose scope and I am left with what I presume to be copies in the vector. How can I go about deleting these. I don't want to store pointers in the array as I will need to pass an API function an array of doubles.

Please someone - how do I delete these objects?

#include <iostream>
#include <vector>

using namespace std;

vector<double> vectorDouble;
void createObjects();

void createObjects() {
    double* a=new double(13);
    double* b=new double(14);
    double* c=new double(15);
    //a,b and c are not contiguous memory blocks
    cout << "memory location of a: " << a << endl;
    cout << "memory location of b: " << b << endl;
    cout << "memory location of c: " << c << endl;

    vectorDouble.push_back(*a);
    vectorDouble.push_back(*b);
    vectorDouble.push_back(*c);
}

int main() {
    createObjects();
    //the memory addresses are contiguous 8 byte chunks
    cout << "vector memory at 0: " << &(vectorDouble[0]) << endl;
    cout << "vector memory at 1: " << &(vectorDouble[1]) << endl;
    cout << "vector memory at 2: " << &(vectorDouble[2]) << endl;

    //get pointer to the 2nd element
    double *P=&(vectorDouble[1]); 

    //dereference and look inside - two memory locations both contain the value 14
    cout << "vector Pointer P ["<< P <<"] contains " << *P <<endl;

    //Which should I call delete on? I have lost reference to the original pointers.
    //How should I call delete on the vector?

    cout << "deleting pointer that references 2nd vector element" << endl;
    delete P; //********* CRASH **********
    cout << "Done deleting" << endl;
}

回答1:

The objects you need to delete are not in the vector, because your vector elements are not created with new. You are just passing the copy of the malloc'd doubles, not the actual allocated double to the vector, when you use the dereference operator in the push_back.

You are actually just leaking them - your code would run fine without allocating doubles:

void createObjects() {
    vectorDouble.push_back(13);
    vectorDouble.push_back(14);
    vectorDouble.push_back(15);
}


回答2:

As everyone points out, there is no reason whatsoever to invoke new in your program:

void createObjects() {
    vectorDouble.push_back(13);
    vectorDouble.push_back(14);
    vectorDouble.push_back(15);
}

Suppose, however, that you do have some reason to call new. (I can't imagine what it might be, but let's assume you are a genius). Here is how you would do that:

void createObjects() {
    double* a=new double(13);
    double* b=new double(14);
    double* c=new double(15);
    //a,b and c are not contiguous memory blocks
    cout << "memory location of a: " << a << endl;
    cout << "memory location of b: " << b << endl;
    cout << "memory location of c: " << c << endl;

    vectorDouble.push_back(*a);
    vectorDouble.push_back(*b);
    vectorDouble.push_back(*c);

    delete a;
    delete b;
    delete c;
}

You see, the push_back doesn't put a copy of your pointer in the vector, it puts a copy of your object in the vector. Once you've made the copy of your object, then your object's memory serves no continuing purpose, and can be destroyed.



回答3:

The function createObjects is not putting the allocated values into the vector; it is putting in the values and then leaking the memory that a, b, and c pointed to. The call:

vectorDouble.push_back(*a);

stores the value pointed to by a in the vector (*a dereferences the pointer, which you probably already know). Once that function returns, the pointers are lost. You cannot retrieve them from the vector. You would either need to make a vector of pointers to doubles or (more likely) don't even allocate values; just store the doubles.



回答4:

I think I've got the problem, on:

vectorDouble.push_back(*a);
vectorDouble.push_back(*b);
vectorDouble.push_back(*c);

You are passing a, b and c as values so the array don't really contains the variables you have created (that's why they now have different memory address, they are a copy of the content of your variables!). Then you can delete the variables inside the method, don't use pointers inside the method or use an double* vector.



回答5:

Your leak is in createObjects(), because std::vector<>::push_back() makes a copy of its argument. You should delete the pointer before the end of scope of createObjects().

That said, I don't see why you use dynamic allocation to begin with. If you can avoid that please do (and you can, with a smart pointer like std::unique_ptr<>, or better yet with plain old doubles).



标签: c++ stl vector