This is related to my other post. One of the suggestions here was to use vector for class Region.. as illustrated in the following code. I have a few more beginner questions --
a) How to allocate this vector a size = numOfRegions? Or do I really need to allocate a size to a vector?
b) How do I insert objects of class Region to this vector<Region>? All these Region objects need to be managed by class A
c) I am assuming I don't need to delete this vector in class A's distructor .. correct?
struct elemt {
int* vertex;
int foo1;
double foo2;
};
class Region{
public:
std::vector <elemt*> elements;
int info;
}
class A{
public:
std::vector<Region> reg;
const int numOfRegions = 100;
}
A::A(){
// how to create and append Region object to vector std::vector<Region> reg ??
// Do I need to allocate size for this region vector?
}
A::~A(){
//do nothing
// Do I need to delete vector<Region> reg here ??
}
A::doSomething(){
// here I want to append the elements to the vector
// Let i be region 10.
// Let e1 be an element of "struct elemt" that needs to be added
reg[i].elements.push_back(e1);
}
Call vector.reserve if you know the size of your vector up front. This isn't required because push_back will resize the vector when needed
vector.push_back(Region());
You don't have to delete member vector
a) the vector does all the memory management for you, you don't need to specify a size. However you can, if you want, call vector::reserve to allocate enough memory (this is only a matter of optimisation)
b) reg.push_back(Region());
c) you don't have to delete the vector as it is in the stack. But you probably want to delete the contents of the vector elements in the class Region.
Related
I have this class:
class aa
{
public:
int i = 0;
~aa(){
std::cout << "killin in the name of" << std::endl;
}
};
And I want to make a vector of this class. First I thought o reserving the needed size:
int main()
{
std::vector<aa> vec;
vec.reserve(2);
vec[0] = *(new aa());
vec[1] = *(new aa());
//use the vector
vec.clear();
return 0;
}
But the destructor was not called.
On the other side, when I fill the Vector using push_back
int main()
{
std::vector<aa> vec;
vec.push_back(*(new aa()));
vec.push_back(*(new aa()));
//use the vector
vec.clear();
return 0;
}
I actually get the destructor called.
Why?
A std::vector already does this memory management for you.
When you use an std::vector with simple classes like this, you do not need any new or delete calls.
reserve
Under the hood, reserve is just making sure that a chunk of memory is preallocated to hold the specified number of member variables.
resize
Under the hood, resize will actually create n new objects. You do not need to explictly call new.
Your example
The code *(new aa()) will create a new aa object on the heap. When you write vec[0] = *(new aa()); it will attempt to copy the contents of your new object to the object that lives in the address vec[0]. Thus there are 2 distinct objects alive at this point in time ... one object vec[0] at one place in memory, and one object elsewhere in memory.
What's worse is that you have now called new and never deleted that object. You thus have a memory leak.
What you probably want
Almost certainly, what you will want one of these scenarios.
Create a vector, and then resize it to have n elements. Then use those elements:
int main() {
std::vector<aa> vec;
vec.resize(2);
vec[0].i = ...;
vec[1].i = ...;
//use the vector
return 0;
}
push_back elements when you want to add things
int main() {
std::vector<aa> vec;
vec.push_back(aa()); // Creates a new aa instance and copies into the vector
aa obj;
vec.push_back(obj); // Copies the existing object's data into a new object in the vector.
//use the vector
return 0;
}
The destructor of vector will delete all of the memory appropriately. No need to explicity clear in this example.
There are more advanced ways that you can use vector, but until you understand this code, you probably should just stick to these basics.
Having a struct such as:
struct PAIR {
vector<double> a;
vector<double> b;
};
Is using a function like the following a proper way to release the memory after defining and populating such a struct? If not, how do you deal with this situation?
void release(PAIR& p){
vector<double>().swap(p.a);
vector<double>().swap(p.b);
}
Isn't there a way to call some predefined/std function on PAIR itself to release memory?
Note that I'm not using new, etc. so definitions are simply like PAIR p;. Also, the struct is much more complex than just a pair of vectors that could have been defined using a std::pair.
All the related questions in SO on releasing memory for vectors are either about vectors themselves or vectors of a struct, not a struct containing multiple vectors. I'm looking for an elegant way to release memory used by such a struct.
Context
The vectors get really big, and I want to release the memory as soon as I can. But that lifetime/usability reaches in the middle of function! I don't want to spread the functionality in this function to multiple functions. These are pretty complicated computations and don't want to mess things up.
Given function does not release memory on the stack actually. It is approximately equivalent to
p.a.clear();
p.a.shrink_to_fit();
The vector itself remains in the memory (just with 0 elements).
Remember, any memory that was allocated on the stack (~ without the use of new) gets released only when the variable occupying this memory goes out of scope, not earlier.
So if you have a variable on the stack and want to delete it, you can just limit its scope:
struct PAIR {
vector<double> a;
vector<double> b;
};
int main()
{
// some stuff before...
{
PAIR p;
// some stuff with p object...
} // here p gets deleted (all memory gets released)
// some stuff after...
}
You mentioned new PAIR. With pointers it would look like this:
int main()
{
// some stuff before...
PAIR* p = new PAIR;
// some stuff with p object...
delete p; // here p gets deleted (all memory gets released)
// some stuff after...
}
Or as commentators requested:
int main()
{
// some stuff before...
{
auto p = std::make_unique<PAIR>();
// some stuff with p...
} // here p gets deleted (all memory gets released)
// some stuff after...
}
Is that what you wanted to achieve?
Does PAIR have to be a POD? Maybe something like this might work for you?
struct PAIR
{
private:
std::unique_ptr<std::vector<double>> aptr;
std::unique_ptr<std::vector<double>> bptr;
PAIR(const PAIR&) = delete;
public:
PAIR() : aptr(std::make_unique<std::vector<double>()),
bptr(std::make_unique<std::vector<double>()) {}
~PAIR() { release(); }
std::vector<double> &a = *aptr;
std::vector<double> &b = *bptr;
void release()
{
aptr.reset();
bptr.reset();
}
...
};
simply .resize(0) the vectors.
Today i went back and investigated an error i got in an old project. It's not exactly an error, rather, i don't know how to do what i need to do. Don't really want to go into the details of the project as it is old and buggy and inefficient and more importantly irrelevant. So i coded a new sample code:
#include <iostream>
#include <vector>
#include <time.h>
#include <random>
#include <string>
class myDoc;
class myElement
{
int myInt;
std::string myString;
myElement * nextElement;
//a pointer to the element that comes immediately after this one
public:
myElement(int x, std::string y) : myInt(x), myString(y){};
friend myDoc;
};//an element type
class myDoc
{
std::vector<myElement> elements;
public:
void load();
~myDoc()
{
//I believe i should delete the dynamic objects here.
}
};// a document class that has bunch of myElement class type objects as members
void myDoc::load()
{
srand(time(0));
myElement * curElement;
for (int i = 0; i < 20; i++)
{
int randInt = rand() % 100;
std::string textInt = std::to_string(randInt);
curElement = new myElement(randInt,textInt);
//create a new element with a random int and its string form
if (i!=0)
{
elements[i-1].nextElement = curElement;
//assign the pointer to the new element to nextElement for the previous element
//!!!!!!!!!!!! this is the part that where i try to create a copy of the pointer
//that goes out of scope, but they get destroyed as soon as the stack goes out of scope
}
elements.push_back(*curElement);// this works completely fine
}
}
int main()
{
myDoc newDoc;
newDoc.load();
// here in newDoc, non of the elements will have a valid pointer as their nextElement
return 0;
}
Basic rundown: we have a document type that consists of a vector of element type we define. And in this example we load 20 random dynamically allocated new elements to the document.
My questions/problems:
When the void myElement::load() function ends, the pointer and/or the copies of it goes out of scope and get deleted. How do i keep a copy that stays(not quite static, is it?) at least until the object it points to is deleted?
The objects in the elements vector, are they the original dynamically allocated objects or are they just a copy?
I allocate memory with new, how/when should i delete them?
Here is a picture i painted to explain 1st problem(not very accurate for the specific example but the problem is the same), and thank you for your time.
Note: I assumed you want a vector of myElement objects where each one points to the element next to it. It is unclear if you want the objects in elements to point to copies of them, anyway it should be pretty easy to modify the code to achieve the latter
This is what happens in your code:
void myDoc::load()
{
..
curElement = new myElement(n,m); // Create a new element on the heap
...
// If this is not the first element we inserted, have the pointer for the
// previous element point to the heap element
elements[i-1].nextElement = curElement;
// Insert a COPY of the heap element (not the one you stored the pointer to)
// into the vector (those are new heap elements copied from curElement)
elements.push_back(*curElement);// this works completely fine
}
so nothing gets deleted when myDoc::load() goes out of scope, but you have memory leaks and errors since the pointers aren't pointing to the elements in the elements vector but in the first heap elements you allocated.
That also answers your second question: they're copies.
In order to free your memory automatically, have no leaks and point to the right elements you might do something like
class myElement
{
int a;
std::string b;
myElement *nextElement = nullptr;
//a pointer to the element that comes immediately after this one
public:
myElement(int x, std::string y) : a(x), b(y){};
friend myDoc;
};//an element type
class myDoc
{
std::vector<std::unique_ptr<myElement>> elements;
public:
void load();
~myDoc()
{}
};// a document class that has bunch of myElement class type objects as members
void myDoc::load()
{
srand((unsigned int)time(0));
for (int i = 0; i < 20; i++)
{
int n = rand() % 100;
std::string m = std::to_string(n);
//create a new element with a random int and its string form
elements.emplace_back(std::make_unique<myElement>(n, m));
if (i != 0)
{
//assign the pointer to the new element to nextElement for the previous element
elements[i - 1]->nextElement = elements[i].get();
}
}
}
Live Example
No need to delete anything in the destructor since the smart pointers will be automatically destroyed (and memory freed) when the myDoc element gets out of scope. I believe this might be what you wanted to do since the elements are owned by the myDoc class anyway.
I have this small program as i am trying to understand the vector and the classname being passed as an argument. Here is the program:
#include<iostream>
#include<vector>
using namespace std;
class objectclass{
public:
void vec_try(){
cout<<"print out something";
}
};
class another{
public:
void run();
vector<objectclass *>ports;
void add_obj(objectclass *p){
ports.push_back(p);
}
};
void another::run(){
//int j=0;
ports[j]->vec_try();
}
int main(){
another a;
a.run();
system("pause");
return 0;
}
i have idea that passing classname in vector as an object is fine and then using push_back to insert the element in that vector but in the function add_obj(objectclass *p) how do i pass the values if i dont want to change the defination of the function. i know a way like this:
objectclass *p;
p= new objectclass[10];
but my function has already defination and also i want to call the function vec_try() with ports[i] so i am not getting how to pass the values and the how this is working with ports[i]. i basically need some clarification on this.
Your add_obj function takes pointers to objectclass objects. So to add elements to your vector, you need to do:
another a;
objectclass obj1; // Create an objectclass
a.add_obj(&obj1); // Pass its address to add_obj
objectclass obj2;
a.add_obj(&obj2);
objectclass obj3;
a.add_obj(&obj3);
Of course, your vector is keeping pointers to these objects. When these objects go out of scope and are destroyed, these pointers will be left pointing at invalid object. But that doesn't matter here, because your objects are only destroyed at the end of main.
An alternative would be to dynamically allocate your objects:
another a;
a.add_obj(new objectclass());
a.add_obj(new objectclass());
a.add_obj(new objectclass());
Each line dynamically allocates an objectclass object, then passes a pointer to that object to add_obj. However, you will need to make sure that you eventually delete this objects in some way or another.
The first element that you push_back into the vector will have index 0, the second will have index 1, the third will have index 2, and so on.
If in run, you want to iterate over all objects in the vector, you can do it something like this:
for (int i = 0; i < ports.size(); i++) {
ports[i]->vec_try();
}
As you can see, this loops through all the elements in the vector (from 0 to ports.size()) and calls vec_try on each one.
There is a better way to do this using iterators, but I'll leave that for a future lesson.
I have a struct like this:
struct foo {
int a,b,c;
float d;
float *array1;
float *array;
};
And now I use this struct for a 8x8 2D-Vector like this:
vector< vector<foo> > bar(8);
for (int i = 0; i < 8; i++)
bar[i].resize(8);
Within my program, "bar" is now filled with data, for example:
bar[1][5].array1 = new float[256];
bar[1][5].array2 = new float[256];
// Et cetera.
How can I free the memory used by bar correctly?
I tried a for-loop for freeing every float array like this:
delete [] bar[i][j].array1;
But that will result in a heap exception on runtime.
Add a destructor to your struct to clean up those members.
Alternatively you could do as Eduardo León suggests and allocate them as part of the structure.
float array1[256];
instead of
float *array1;
First of all, you ought to use vector<float> instead of float*, arrays are evil.
Second, the way you are freeing the memory is correct, the mistake must be at some other place.
Can you post an actual code fragment? If you're deleting just the elements you're allocating, there shouldn't be a problem.
I'd suggest a couple things to help narrow it down:
Assign NULL to all your pointers on initialization
Use shared_ptr types instead of raw float pointers - these will be automatically cleaned up when no references remain.
I suggest you use an vector or other stl-container, which fits your need.
If it has to be arrays - better use an destructor in your struct, so you need not to think about manually cleanup:
struct foo
{
int a,b,c;
float d;
float *array1;
float *array2;
foo ()
: a(0),
b(0),
c(0),
d(0.0),
array1(NULL),
array2(NULL)
{ }
~foo ()
{
delete [] array1;
delete [] array2;
}
};
edit: removed check of NULL on delete []
This easiest way to accomplish this would be to create a constructor and destructor:
struct foo {
int a,b,c;
float d;
float *array1;
float *array;
foo()
{
array1 = array = 0;
}
~foo()
{
delete [] array1;
delete [] array;
}
};
Even better would be members to track the size of array1 & array so that a copy constructor and/or assignment operator could clone them as needed.
Note: by "easiest" I do not mean "best". :)
You have to add this destructor to your struct foo:
~foo() {
delete []array1;
delete []array2;
}
I suggest also to create a constructor for you foo that initializes those two pointers to 0:
foo()
:a(0),b(0),c(0),
d(0.0), array1(0), array2(0)
{}