如何创建一个指向矢量的指针向量

Roa*_*ash 5 c++ pointers vector

我有一个指向矢量的指针:

vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
vector<double>* new_mv_pt = new vector<double> (3);
new_mv_pt = &mv;    

cout << (*new_mv_pt)[1] << endl;    
Run Code Online (Sandbox Code Playgroud)

如何创建另一个将此指针存储到向量的向量?我正在尝试这个......

    vector<double*> vop = new vector<double> (3);

vop.push_back(*new_mv_pt);

cout << (*vop)[1] << endl;
Run Code Online (Sandbox Code Playgroud)

但它不起作用.我正在尝试甚至可能吗?:

小智 7

Whoa, slow down there!

You're doing some pretty crazy things with your memory, so let's start from the beginning.

You have a single vector that has 3 elements in it. You want to reference that vector using a pointer. Let's see how that looks:

vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// No no no no! You don't have to `new` a pointer that 
// you're going to assign to something else!
// This is called a memory leak, and it means you've just wasted (!!!)
// C++ memory! Don't do it 
// vector<double>* new_mv_pt = new vector<double> (3);
// Instead, do this:
vector<double>* ptr_to_mv = &mv; // No leak, immediately points to a vector<double> mv;
Run Code Online (Sandbox Code Playgroud)

That takes care of the first bit. Now, let's get into it a bit deeper. You want to store a vector of references to vectors. Alright, that sounds fair. There's a few ways to go about it. Let's go back to the example of mv and other things:

vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
vector<double>* ptr_to_mv = &mv;
// So far so good. Now, based on your question, you want
// to have a list of these to point to. So:
vector<vector<double>*> vop;
vop.push_back( ptr_to_mv ); // All clean.
Run Code Online (Sandbox Code Playgroud)

At this point in your code, you have to access vop with .at() or the operator[] to get to a vector<double>*, then you dereference it with * or use -> to work on it directly:

std::vector<double>* ptr_to_vector = vop[0]; // Got my pointer
std::cout << ptr_to_vector->at( 0 ) << std::endl; // Prints '233'
Run Code Online (Sandbox Code Playgroud)

This prints 233 because all of this is you referencing mv. In a comment in another answer, you said that when you delete these pointers, you get an assertion. This is supposed to happen, because you're deleting things twice!

Remember mv, that you declared a long time ago? Well, you didn't make it a dynamic vector.You didn't new it, and it's no pointer. So when the function exits, it will automatically delete itself - it will call its destructor and die on the stack. If you look at ptr_to_vector or ptr_to_mv, they're all referencing mv, which cleans itself.

If you call delete on it, you're trying to call delete on mv (that's what you're pointing to) and you're double-deleting!

So, when you have a pointer to mv, don't delete it. It's a stack-based variable. It will clean itself up.

Still following? Great, let's get into it a bit more:

Now, if there's a reason you need to new up a vector, you don't assign override it with an old pointer (as I told you before, you'll leave memory). You make a completely fresh new pointer:

// Our vector of double vector pointers
vector<vector<double>*> vop;

vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);

// References a stack variable: don't delete
vector<double>* ptr_to_mv = &mv;
vop.push_back( ptr_to_mv );

// Makes a fresh copy of mv. You must delete this
// manually
vector<double>* fresh_ptr = new vector<double>( mv );
(*fresh_ptr)[0] = 1337;
// changes only data in fresh_ptr, not `mv`
vop.push_back( fresh_ptr );

/* Blah blah blah, work */
// Functions about to exit, gotta clean up!
delete fresh_ptr;
//delete ptr_to_mv; // NO.
//delete vop[0]; // NO!
//delete vop[1]; // ... Already deleted from fresh_ptr
// ... This is going to get tedious if we don't have a fresh_ptr
// for every vector we need!
Run Code Online (Sandbox Code Playgroud)

The above shows the problem: we have 2 pointers, both inside vop, where one needs to be cleaned up by calling delete, and another that doesn't because it's just a reference to mv, which cleans automatically! Looping over the vector and deleting everything will cause that nasty assertion to happen. How do we deal with it and still get the clean up we need?

Dirty and Quick Solution 1 is to just delete vop[1]/fresh_ptr and be done with it. The better solution is that, whenever you new up a resource, you wrap it up in this wonderful thing called a std::unique_ptr. The code will look like this:

// Our vector of double vector pointers. Non-owning
vector<vector<double>*> vop;

vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);

// References a stack variable: don't delete
vector<double>* ptr_to_mv = &mv;
vop.push_back( ptr_to_mv );

// Makes a fresh copy of mv
// puts it inside a std::unique_ptr,
// which, like a stack-based vector,
// can clean itself up
std::unique_ptr<vector<double>> fresh_ptr( new vector<double>( mv ) );
vop.push_back( fresh_ptr.get() );

/* Blah blah blah, work */
// Functions about to exit, gotta clean up!
//delete fresh_ptr; // Not necessary
//delete ptr_to_mv; // Nope.jpg
Run Code Online (Sandbox Code Playgroud)

And there you go, remove all that commented-out code and suddenly, your stuff is clean as a whistle!

Of course, now, the final question I have for you is: What the hell are you doing that requires all these pointers to pointers to references of pointers of vectors?


Fan*_*Fox 3

是的,但你需要这样做:

vector<vector<double>*> vop;
Run Code Online (Sandbox Code Playgroud)

因为您正在寻找向量指针列表。

你这里有什么:

vector<double *> vop
Run Code Online (Sandbox Code Playgroud)

只是一个double指针向量。

你也只想要这个:

vop.push_back(new_mv_pt); //  <- No asterisk (you don't want to de-reference it)
Run Code Online (Sandbox Code Playgroud)