473,385 Members | 1,707 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Storing objects in vectors - what's wrong with this code?

I have written the following code, to test the concept of storing
objects in a vector. I encounter two run time errors:

1). myClass gets destructed when pushed onto the vector
2). Prog throws a "SEGV" when run (presumably - attempt to delete
deleted memory.

Please take a look and see if you can notice any mistakes I'm making.
Basically, I want to store classes of my objects in a vector. I also
have three further questions:

1). What happens to my objects when erase() or clear() is invoked on the
container vector?

2). What is the best way to create new objects for pushing on to the
vector (the new keyword returns a pointer to the class - which suggests
I should probably be storing *pointers* to the class rather than the
class itself? - but push_back() has signature push_back(const T&) - I'm
confused)

3). Do I have to manually handle destruction of my objects when:

(a) pop_back is invoked on the vector (in this case what happens to my
last element?)
(b). The vector is resized (who frees my objects at the end?)
(c). The vector goes out of scope and its destructor is called?
Here is the code snippet mentioned previously:

#include <vector>
#include <iostream>

using namespace std ;

class MyClass {
public:
MyClass(){
cout << "cstor called !" << endl ;
i = new int ;
*i = 100 ;
}

virtual ~MyClass(){
cout << "dstor called !" << endl ;
delete i ;
}

int getVal(void){ return *i ; }
void setVal(int v){ *i=v ;}

private:
int* i ;
};

int main(int argc, char* argv[])
{
MyClass mc ;
std::vector<MyClass> mv ;

mv.push_back(mc) ; // Crashes here. Also I want to store
// a dynamic number of objects in the
// vector. How may I do this?
mv.clear ;
return 0;
}

Jul 23 '05 #1
6 2536
> I have written the following code, to test the concept of storing
objects in a vector. I encounter two run time errors:

1). myClass gets destructed when pushed onto the vector
2). Prog throws a "SEGV" when run (presumably - attempt to delete
deleted memory.

Please take a look and see if you can notice any mistakes I'm making.
Basically, I want to store classes of my objects in a vector. I also
have three further questions:

1). What happens to my objects when erase() or clear() is invoked on the
container vector?

2). What is the best way to create new objects for pushing on to the
vector (the new keyword returns a pointer to the class - which suggests
I should probably be storing *pointers* to the class rather than the
class itself? - but push_back() has signature push_back(const T&) - I'm
confused)

3). Do I have to manually handle destruction of my objects when:

(a) pop_back is invoked on the vector (in this case what happens to my
last element?)
(b). The vector is resized (who frees my objects at the end?)
(c). The vector goes out of scope and its destructor is called?
Here is the code snippet mentioned previously:

#include <vector>
#include <iostream>

using namespace std ;

class MyClass {
public:
MyClass(){
cout << "cstor called !" << endl ;
i = new int ;
*i = 100 ;
}

virtual ~MyClass(){
cout << "dstor called !" << endl ;
delete i ;
}

int getVal(void){ return *i ; }
void setVal(int v){ *i=v ;}

private:
int* i ;
};

int main(int argc, char* argv[])
{
MyClass mc ;
std::vector<MyClass> mv ;

mv.push_back(mc) ; // Crashes here. Also I want to store
// a dynamic number of objects in the
// vector. How may I do this?
mv.clear ;
return 0;
}


You need to provide a copy constructor. A default copy constructor is used
so a copied MyClass will share the same inner i, which, when deleted, will
cause problems.

ben
Jul 23 '05 #2
Alfonso Morra wrote:
I have written the following code, to test the concept of storing
objects in a vector. I encounter two run time errors:

1). myClass gets destructed when pushed onto the vector
2). Prog throws a "SEGV" when run (presumably - attempt to delete
deleted memory.

Please take a look and see if you can notice any mistakes I'm making.
Basically, I want to store classes of my objects in a vector. I also
have three further questions:

1). What happens to my objects when erase() or clear() is invoked on the
container vector?
Since what you have in a vector is a copy of your elements, calling
erase() or clear() in a vector does not have any effects on your
variables (which are obviously not vector elements but a copy of it).
2). What is the best way to create new objects for pushing on to the
vector (the new keyword returns a pointer to the class - which suggests
I should probably be storing *pointers* to the class rather than the
class itself? - but push_back() has signature push_back(const T&) - I'm
confused)
No

std::vector<MyClass> mv ;

defines a vector mv which can accomodate 'MyClass' objects, and what
you are pushing in the vactor is mc which is a MyClass object, which is
absolutely fine. So, far so good.
3). Do I have to manually handle destruction of my objects when:

(a) pop_back is invoked on the vector (in this case what happens to my
last element?)
pop_back() returns a copy of the last element from a vector, the
original copy from the vector has been deleted. So, all the local
objects will automatically get deleted. I don't see anywhere new
(outside class MyClass), so no question of manually destructing
objects.
(b). The vector is resized (who frees my objects at the end?)
When the vector gets resized is the the vectors job to efficiently move
elements and destroy any temporaraies created during this job, so you
are not the one who really needs to worry about it, unless you are
writing a vector ofcourse.
(c). The vector goes out of scope and its destructor is called?

When a vector goes out of scope, its destructor calls destructors for
all of its elements, so all the cleanup is supposed to be done by the
vector.
You have problem somewhere else. See my comments below:

Here is the code snippet mentioned previously:

#include <vector>
#include <iostream>

using namespace std ;

class MyClass {
public:
MyClass(){
cout << "cstor called !" << endl ;
i = new int ;
*i = 100 ;
}

virtual ~MyClass(){
cout << "dstor called !" << endl ;
delete i ;
}
If you think, you need any one of copy constructor, assignment operator
and destructor, you need all of these.

Define a copy constructor and an assignment operator
MyClass ( const MyClass& m ) {
i = new int;
*i = m.getVal();
}
MyClass& operator= ( const MyClass& m ) {
i = new int;
*i = m.getVal();
return *this;
}
int getVal(void){ return *i ; }
Define getVal() before the copy constructor as it uses it.
void setVal(int v){ *i=v ;}

private:
int* i ;
Your class has a char*, you need a suitable copy constructor. };

int main(int argc, char* argv[])
{
MyClass mc ;
std::vector<MyClass> mv ;

mv.push_back(mc) ; // Crashes here. Also I want to store
// a dynamic number of objects in the
// vector. How may I do this?
mv.clear ;
return 0;
}


Since there was not a copy constructor, the default copy constructor
copies the pointers while copying i. So, after the copy, both objects
point to the same memory location created in constructor using new.
This is bad, because when one gets out of scope, its destructor gets
called, which frees up to allocated memory. The otherone's i is still
pointing to the same memory this is a disaster.

/P

Jul 23 '05 #3


pk******@gmail.com wrote:
Alfonso Morra wrote:
I have written the following code, to test the concept of storing
objects in a vector. I encounter two run time errors:

1). myClass gets destructed when pushed onto the vector
2). Prog throws a "SEGV" when run (presumably - attempt to delete
deleted memory.

Please take a look and see if you can notice any mistakes I'm making.
Basically, I want to store classes of my objects in a vector. I also
have three further questions:

1). What happens to my objects when erase() or clear() is invoked on the
container vector?

Since what you have in a vector is a copy of your elements, calling
erase() or clear() in a vector does not have any effects on your
variables (which are obviously not vector elements but a copy of it).

You seem to misunderstand my question. Granted, the objects in the
vector are copies of the originals. My question was that what happens to
the objects *in the vector container* when a clear() or erase() is
called - do they get freed?

On a slightly different note - since a vector stores a copy of the item
to be stored, it behooves me to delete the original copy(ies) , since I
do not want two copies, floating about - maybe it would be better to
store pointers to my object instead?. It seems quite
inefficient/expensive of going through the steps of:

i). Object creation
ii). Making copy of the object
iii). Deleting the original object (so only the copy in the vector is kept)

It just dosen't seem right ...
2). What is the best way to create new objects for pushing on to the
vector (the new keyword returns a pointer to the class - which suggests
I should probably be storing *pointers* to the class rather than the
class itself? - but push_back() has signature push_back(const T&) - I'm
confused)


No

std::vector<MyClass> mv ;

defines a vector mv which can accomodate 'MyClass' objects, and what
you are pushing in the vactor is mc which is a MyClass object, which is
absolutely fine. So, far so good.

3). Do I have to manually handle destruction of my objects when:

(a) pop_back is invoked on the vector (in this case what happens to my
last element?)

pop_back() returns a copy of the last element from a vector, the
original copy from the vector has been deleted. So, all the local
objects will automatically get deleted. I don't see anywhere new
(outside class MyClass), so no question of manually destructing
objects.

(b). The vector is resized (who frees my objects at the end?)

When the vector gets resized is the the vectors job to efficiently move
elements and destroy any temporaraies created during this job, so you
are not the one who really needs to worry about it, unless you are
writing a vector ofcourse.

(c). The vector goes out of scope and its destructor is called?

When a vector goes out of scope, its destructor calls destructors for
all of its elements, so all the cleanup is supposed to be done by the
vector.
You have problem somewhere else. See my comments below:


Thanks for the correction and pointers
/P


Jul 23 '05 #4
Remember the rule of 3:
If there's a need to define the destructor of a class,
you'll also need to provide the copy constructor
and the assignment operator.

regards, Stephan

Jul 23 '05 #5
Alfonso Morra wrote:


pktiwary at gmail.com wrote:
Since what you have in a vector is a copy of your elements, calling
erase() or clear() in a vector does not have any effects on your
variables (which are obviously not vector elements but a copy of it).

You seem to misunderstand my question. Granted, the objects in the
vector are copies of the originals. My question was that what happens to
the objects *in the vector container* when a clear() or erase() is
called - do they get freed?


I think that would probably depend on the allocator of the vector, but generally, I suspect the destructor is called, and the memory freed.
On a slightly different note - since a vector stores a copy of the item
to be stored, it behooves me to delete the original copy(ies) , since I
do not want two copies, floating about - maybe it would be better to
store pointers to my object instead?. It seems quite
inefficient/expensive of going through the steps of:

i). Object creation
ii). Making copy of the object
iii). Deleting the original object (so only the copy in the vector is kept)

It just dosen't seem right ...


1) You could let the original go out of scope... depending on what you do with this, I suspect the compiler will optimise the copy.

2) You could create the original directly in the vector:

mv.push_back(MyClass());

//Although on VS .NET you still get 1 construction, presumably two copies and 3 destructions whether you use the temporory or not.

2). What is the best way to create new objects for pushing on to the
vector (the new keyword returns a pointer to the class - which suggests
I should probably be storing *pointers* to the class rather than the
class itself? - but push_back() has signature push_back(const T&) - I'm
confused)


MyClass is a type
MyClass* is also a completely valid, different type.

You can do:

std::vector<MyClass*> mv;

If you like, but it means keeping track of your pointers, so don't do this:
mv.push_back(new MyClass());

And definately don't try to use an auto_ptr to manage it.

Also, I fail to see the point of having your int member of MyClass a pointer, whats wrong with:

class MyClass {
public:
MyClass() : i(100) {
cout << "cstor called !" << endl ;
}

virtual ~MyClass(){
cout << "dstor called !" << endl ;
}

int getVal(void){ return i ; }
void setVal(int v){ i=v ;}

private:
int i;
};

In that case the compiler provided copy and assignment will be fine.

Ben
--
I'm not just a number. To many, I'm known as a String...
Jul 23 '05 #6
Alfonso Morra wrote:
I have written the following code, to test the concept of storing
objects in a vector. I encounter two run time errors:

1). myClass gets destructed when pushed onto the vector
MyClass is a class, not an object. It cannot be destructed. In the code
below, nothing is supposed to get destroyed on the line

mv.push_back(mc) ;
2). Prog throws a "SEGV" when run (presumably - attempt to delete
deleted memory.
Yes, that's not surprising.
Please take a look and see if you can notice any mistakes I'm making.
Basically, I want to store classes of my objects in a vector. I also
No, you want to store MyClass objects in the vector. Be careful with
names!
have three further questions:

1). What happens to my objects when erase() or clear() is invoked on the
container vector?
Depends on what you mean by 'my objects'. A std::vector manages its
memory and its elements. For example:

std::vector<int> v;
for (int i=0; i<10; ++i)
v.push_back(i);

Here, when the vector goes out of scope, it will manage its ten ints.
That means you don't have to worry about it. A vector will usually be
implemented with a dynamic array, which means it will delete the its
memory with delete[], which will call the destructors for all the
objects.

Now, it does the same thing for pointers. The problem with pointers is
that they usually point to something which must be manually deleted. So
the vector will destroy all the pointers correctly, but not the objects
pointed at. You'll have to do this manually.

int main()
{
std::vector<int*> v;
for (int i=0; i<10; ++i)
v.push_back(new int(i));

// v will leak the ints if you dont do that:
for (int i=0; i<10; ++i)
delete v[i];

// but v will never leak the pointers you pushed
}

2). What is the best way to create new objects for pushing on to the
vector
Depends. If you don't want copies to be made (for example, if the
objects are really big to copy, or if the identity of each object is
important), you'll want to store pointers. Since you are storing
pointers, you will need the object pointed at to last longer than
usual: you'll need dynamic memory.

If you can make copy as you wish, put objects by value in the
containers. It may seem 'inefficient', but it will save you a lot of
trouble.
(the new keyword returns a pointer to the class -
The new keyword return a pointer to a newly allocated object.
which suggests
I should probably be storing *pointers* to the class rather than the
class itself? -
If you want to use dynamic memory, yes, you'll have to store pointers
to the 'objects' rather than the 'objects' themselves. But I don't
think you need dynamic memory, certainly not for the example code
below.
but push_back() has signature push_back(const T&) - I'm
confused)
Well the signature is alright if 'T' is 'MyClass*'.

std::vector<int> v;

With this, push_back becomes

push_back(const int &);

and with

std::vector<int*> v;

push_back becomes:

push_back(const int* &);

And a reference to a pointer is like an ordinary pointer (for
simplicity). So whether you have objects or pointers in your vector,
the member functions "adapt" themselves. Actually, that's the essence
of templates.
3). Do I have to manually handle destruction of my objects when:

(a) pop_back is invoked on the vector (in this case what happens to my
last element?)
Again, it depends. The 'object' itself will be destroyed. If the object
is actually a 'pointer', and that pointer points to something you
allocated yourself, you will need to destroy that 'something'.

std::vector<int*> v;

v.push_back(new int(10));

// here, 'v' has a pointer

v.push_back();

// here, 'v' destroyed its pointer, but *not*
// what it pointed at: you just leaked the
// new int

I should have done:

std::vector<int*> v;

v.push_back(new int(10));

// here, 'v' has a pointer

delete v[0];
v.push_back();

// ok!
(b). The vector is resized (who frees my objects at the end?)
WHen a vector is resized, it will never shrink, so that's not a
problem, really.
(c). The vector goes out of scope and its destructor is called?
This is equivalent to a serie of pop_back, so all the discussion above
apply. Again, the vector owns its memory, so it will destroy all the
objects it owns and it will destroy all the memory it owns. If these
objects were pointers, you must destroy the objects they point to
manually.

Here is the code snippet mentioned previously:

#include <vector>
#include <iostream>

using namespace std ;
Not recommended at file scope.
class MyClass {
public:
MyClass(){
cout << "cstor called !" << endl ;
The abbreviation is usually 'ctor'.
i = new int ;
*i = 100 ;
}
Stop.

Your class manages memory. With you have a class which manages memory,
you must remember to rule of three: copy-contructor, assignement
operator and destructor. You have got 1/3, which is 33%. You fail :)

The problem is when you copy a MyClass. Since you have not specified
any copy contructor or assignement operator, the compiler will generate
them. It will copy the pointer (not not the object pointed at).

MyClass m1, m2;
m1 = m2;

Here, m1 and m2 will have their pointer point to the same int in
memory. What's more, you just leaked the int of m1. When m2 will get
out of scope, it will delete its int and then m1 will the delete the
same one. Crash.

"Now I don't make any copies" you say. Well unfortunately, yes, you do.
std::vector, when you insert an object in it, will copy the object. So
std::vector first destroy an object, which deletes an int, and then
your 'mc' object goes out of scope and deletes the same one. Bang.

MyClass(const MyClass &m)
: i(new int(m.i))
{
}

MyClass &operator=(const MyClass &m)
{
delete i;
i = new int(m.i);

return this;
} virtual ~MyClass(){
cout << "dstor called !" << endl ;
delete i ;
}

int getVal(void){ return *i ; }
void setVal(int v){ *i=v ;}

private:
int* i ;
};

int main(int argc, char* argv[])
{
MyClass mc ;
std::vector<MyClass> mv ;

mv.push_back(mc) ; // Crashes here. Also I want to store
// a dynamic number of objects in the
// vector. How may I do this?
std::vector is *meant* to store a dynamic number of objects. Just call
push_back(), insert(), pop_back(), clear(), erase() or whatever as many
times as you want.
mv.clear ;
This should be

mv.clear();

but is not necessary anyways.
return 0;
}

Jonathan

Jul 23 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: Dart | last post by:
This code is okay: class CSingle { public: static CSingle membs; int MEM_NUM; CSingle(int n) { }
1
by: Husam | last post by:
Hi EveryBody: Is there any one know how can I use the following code to make windows application project that can start and stop the windows32 service manually?and tell me what the languege this...
12
by: questions? | last post by:
I am testing a problem with linked list. I just do a lot of times: create a list, then free it. ############################################# # include <stdio.h> # include <stdlib.h> struct...
8
by: Thaqalainnaqvi | last post by:
Several times I logged-in successfully but after log-in I can't use features/services which were shown prior to my login. Can anyone exoert from this forum check , is it technical fault of Bank...
12
by: JC | last post by:
Hi... Anybody knows what problem has this code? I think, in the Garbage Collector? You know the Solution? The program in the test's case, whit 350 contacts, run OK before number 86. The error...
2
by: GaryDean | last post by:
I have inherrited an undocumented asp.net 1.1 application that contains a subproject with about 85 .vb modules that look like they are generated from some kind of data layering tool such as...
1
by: rave3085 | last post by:
Actually this is a part of the code that keeps me wondering why? Dim rsExp As New ADODB.Recordset Dim rsDB As New ADODB.Connection Set rsExp = New ADODB.Recordset ...
6
by: MyMarlboro | last post by:
i wish to compare 1 file with multiple files (in a folder) @allfile - >> the paths for all files in a folder but once i run the code below, it keep loop at print "comparing $masterfile with...
1
by: Michelle Chase | last post by:
Option Compare Database 'this one is to use to concatenate the fields Function combine_descriptions() 'turn off warning dialog DoCmd.SetWarnings (False) Dim rst As Recordset Dim...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.