I have the ff code for testing the concept of storing objects:
#include <vector>
#include <iostream>
using namespace std ;
class MyClass {
public:
MyClass(){
cout << "Default cstor called !" << endl ;
i = new int ;
*i = 100 ;
}
MyClass( const MyClass& m) {
cout << "Copy cstor called !" << endl ;
this->i = new int ;
*(this->i) = *(m.i);
}
MyClass& operator=( const MyClass& m) {
cout << "Assignment called !" << endl ;
if (this != &m) {
MyClass tmp(m) ;
std::swap(this->i, tmp.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) ;
cout << "Element 0 of the vector has i value : " << mv[0].getVal() <<
endl ;
cout << "Setting i value to 123\n" ;
mv[0].setVal(123) ;
cout << "Element 0 of the vector now has i value : " << mv[0].getVal()
<< endl ;
mv.clear() ;
cout << "(After clear) size of vector is : " << mv.size() << endl ;
return 0;
}
Here is output from the console (code execution point is at the point
where variable mc has been "pushed back" into the vector).
Default cstor called !
Copy cstor called !
Copy cstor called !
dstor called !
I have the the following questions:
1). Why is the copy constructor called TWICE?
2). Why is the destructor called after mc has been pushed into the vector?
3). Does the vector implementation guarantee that it will free my
(contained) objects when:
(i) erase() is invoked
(ii) clear() is invoked
(iii) vector goes out of scope?
- since a vector stores a copy of the item to be stored, it behooves me
to delete the original variables (the copies of which are stored in the
vector), since I do not want two copies, "floating about" and consuming
resources - maybe it would be better to store pointers to my object
instead in the vector?. Storing copies rather than the original items in
a vector seems quite an inefficient/expensive way of going about things
- i.e. :
i). Object creation
ii). Making a copy of the object (vector stores a copy not original)
iii). Deleting the original object (so only the copy in the vector is
kept) - to mimimise resource consumption
It just dosen't seem right ... deleting an object that has just been
created (purely for the purposes of making a copy) seems just plain
silly ... Please say it isn't so ...
What (if anything) am I missing?
Looking forward to some insightful answers. Many thanks
Al 12 3894
Alfonso Morra wrote: I have the ff code for testing the concept of storing objects:
#include <vector> #include <iostream>
using namespace std ;
class MyClass { public: MyClass(){ cout << "Default cstor called !" << endl ; i = new int ; *i = 100 ; }
MyClass( const MyClass& m) { cout << "Copy cstor called !" << endl ; this->i = new int ; *(this->i) = *(m.i); }
MyClass& operator=( const MyClass& m) { cout << "Assignment called !" << endl ; if (this != &m) { MyClass tmp(m) ; std::swap(this->i, tmp.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) ; cout << "Element 0 of the vector has i value : " << mv[0].getVal() << endl ; cout << "Setting i value to 123\n" ; mv[0].setVal(123) ; cout << "Element 0 of the vector now has i value : " << mv[0].getVal() << endl ; mv.clear() ; cout << "(After clear) size of vector is : " << mv.size() << endl ;
return 0; }
Here is output from the console (code execution point is at the point where variable mc has been "pushed back" into the vector).
Default cstor called ! Copy cstor called ! Copy cstor called ! dstor called !
Check again, the output above is wrong:
You trace all calls to constructors, assignment operator
and destructor, i.e., the number of calls to the first two
must balance with the destructor calls.
I have the the following questions:
1). Why is the copy constructor called TWICE?
Not if I compile and run your program.
2). Why is the destructor called after mc has been pushed into the vector?
Because push_back creates a copy.
3). Does the vector implementation guarantee that it will free my (contained) objects when: (i) erase() is invoked (ii) clear() is invoked (iii) vector goes out of scope?
The destructor of the "contained objects" will be called,
no memory is freed by the vector except for the last case. - since a vector stores a copy of the item to be stored, it behooves me to delete the original variables (the copies of which are stored in the vector), since I do not want two copies, "floating about" and consuming resources - maybe it would be better to store pointers to my object instead in the vector?. Storing copies rather than the original items in a vector seems quite an inefficient/expensive way of going about things - i.e. :
Think again: How whould you store the original item in the vector?
Could you provide the pseudo code for it?
If the copy construction of a class is expensive, you may use
std::vector<Class*> as STL-container, however then you'll need
to provide a wrapper class that takes care of copy, asssignment
and destruction of the vector. i). Object creation ii). Making a copy of the object (vector stores a copy not original) iii). Deleting the original object (so only the copy in the vector is kept) - to mimimise resource consumption
It just dosen't seem right ... deleting an object that has just been created (purely for the purposes of making a copy) seems just plain silly ... Please say it isn't so ...
What (if anything) am I missing?
Looking forward to some insightful answers. Many thanks
Al
Stephan Brönnimann wrote: Alfonso Morra wrote:
I have the ff code for testing the concept of storing objects:
#include <vector> #include <iostream>
using namespace std ;
class MyClass { public: MyClass(){ cout << "Default cstor called !" << endl ; i = new int ; *i = 100 ; }
MyClass( const MyClass& m) { cout << "Copy cstor called !" << endl ; this->i = new int ; *(this->i) = *(m.i); }
MyClass& operator=( const MyClass& m) { cout << "Assignment called !" << endl ; if (this != &m) { MyClass tmp(m) ; std::swap(this->i, tmp.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) ; cout << "Element 0 of the vector has i value : " << mv[0].getVal() << endl ; cout << "Setting i value to 123\n" ; mv[0].setVal(123) ; cout << "Element 0 of the vector now has i value : " << mv[0].getVal() << endl ; mv.clear() ; cout << "(After clear) size of vector is : " << mv.size() << endl ;
return 0; }
Here is output from the console (code execution point is at the point where variable mc has been "pushed back" into the vector).
Default cstor called ! Copy cstor called ! Copy cstor called ! dstor called !
Check again, the output above is wrong: You trace all calls to constructors, assignment operator and destructor,
What does that mean in plain English ?
i.e., the number of calls to the first two must balance with the destructor calls.
Huh? I have the the following questions:
1). Why is the copy constructor called TWICE? Not if I compile and run your program.
Hmm ....
2). Why is the destructor called after mc has been pushed into the vector? Because push_back creates a copy.
I dont understand the point you're making, creating a copy of a variable
is not the same as deleting the variable - in other words, the fact that
a copy is made of variable mc does not explain why it is fred.
3). Does the vector implementation guarantee that it will free my (contained) objects when: (i) erase() is invoked (ii) clear() is invoked (iii) vector goes out of scope?
The destructor of the "contained objects" will be called, no memory is freed by the vector except for the last case.
Once again, your response seems inconsistent. If the destructor of
"contained objects" is invoked, then - memory is being freed (this is
certainly true in the example I gave of contained object MyClass) - since a vector stores a copy of the item to be stored, it behooves me to delete the original variables (the copies of which are stored in the vector), since I do not want two copies, "floating about" and consuming resources - maybe it would be better to store pointers to my object instead in the vector?. Storing copies rather than the original items in a vector seems quite an inefficient/expensive way of going about things - i.e. :
Think again: How whould you store the original item in the vector? Could you provide the pseudo code for it?
If the copy construction of a class is expensive, you may use std::vector<Class*> as STL-container, however then you'll need to provide a wrapper class that takes care of copy, asssignment and destruction of the vector.
This is axiomatic. I wanted to know *what* (if any) resource management
std::vector provides "out of the box", so I can decide if I need to
"roll my own" resource management logic. i). Object creation ii). Making a copy of the object (vector stores a copy not original) iii). Deleting the original object (so only the copy in the vector is kept) - to mimimise resource consumption
It just dosen't seem right ... deleting an object that has just been created (purely for the purposes of making a copy) seems just plain silly ... Please say it isn't so ...
What (if anything) am I missing?
Looking forward to some insightful answers. Many thanks
Al
Alfonso Morra wrote: I have the ff code for testing the concept of storing objects:
#include <vector> #include <iostream>
using namespace std ;
class MyClass { public: MyClass(){ cout << "Default cstor called !" << endl ; i = new int ; *i = 100 ; }
MyClass( const MyClass& m) { cout << "Copy cstor called !" << endl ; this->i = new int ; *(this->i) = *(m.i); }
MyClass& operator=( const MyClass& m) { cout << "Assignment called !" << endl ; if (this != &m) { MyClass tmp(m) ; std::swap(this->i, tmp.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) ; cout << "Element 0 of the vector has i value : " << mv[0].getVal() << endl ; cout << "Setting i value to 123\n" ; mv[0].setVal(123) ; cout << "Element 0 of the vector now has i value : " << mv[0].getVal() << endl ; mv.clear() ; cout << "(After clear) size of vector is : " << mv.size() << endl ;
return 0; }
Here is output from the console (code execution point is at the point where variable mc has been "pushed back" into the vector).
Default cstor called ! Copy cstor called ! Copy cstor called ! dstor called !
I have the the following questions:
1). Why is the copy constructor called TWICE?
Not sure. My implentation seems to make a temporary local copy, before copying it to where it will end up.
2). Why is the destructor called after mc has been pushed into the vector?
The temporary copy goes out of scope.
3). Does the vector implementation guarantee that it will free my (contained) objects when: (i) erase() is invoked
Yes.
(ii) clear() is invoked
Should be equivelant to:
vec.erase(vec.begin(), vec.end())
(iii) vector goes out of scope?
Yes.
But remember that if you use pointers to your objects, it is the pointers it both copies AND deletes, not the objects they point to.
- since a vector stores a copy of the item to be stored, it behooves me to delete the original variables (the copies of which are stored in the vector), since I do not want two copies, "floating about" and consuming resources - maybe it would be better to store pointers to my object instead in the vector?. Storing copies rather than the original items in a vector seems quite an inefficient/expensive way of going about things - i.e. :
i). Object creation ii). Making a copy of the object (vector stores a copy not original) iii). Deleting the original object (so only the copy in the vector is kept) - to mimimise resource consumption
It just dosen't seem right ... deleting an object that has just been created (purely for the purposes of making a copy) seems just plain silly ... Please say it isn't so ...
What (if anything) am I missing?
The fact that copying probably isn't as expensive as you think, and that you shouldn't prematurely optimise.
You could use a reference counted pointer to store your objects if they really are that expensive to copy. Look at boost smart pointers: http://www.boost.org/libs/smart_ptr/smart_ptr.htm
Benchmark both approaches, but don't forget that something like a reference counted pointer introduces overhead too (counting when you copy, and indirection when you access)
Ben
--
I'm not just a number. To many, I'm known as a String...
Alfonso Morra wrote:
Stephan Brönnimann wrote: Check again, the output above is wrong: You trace all calls to constructors, assignment operator and destructor,
What does that mean in plain English ?
It means he didn;t read the bit that said you hadn't completed the program. i.e., the number of calls to the first two must balance with the destructor calls.
Huh?
In total, you should have 1 construction, 2 copies and 3 destructions. I have the the following questions:
1). Why is the copy constructor called TWICE?
Not if I compile and run your program.
Hmm ....
I get two copies when compiled and run.
Ben
--
I'm not just a number. To many, I'm known as a String...
Ben Pope wrote: Alfonso Morra wrote:
Stephan Brönnimann wrote:
>> Check again, the output above is wrong: You trace all calls to constructors, assignment operator and destructor, What does that mean in plain English ?
It means he didn;t read the bit that said you hadn't completed the program.
i.e., the number of calls to the first two must balance with the destructor calls.
Huh?
In total, you should have 1 construction, 2 copies and 3 destructions.
I have the the following questions:
1). Why is the copy constructor called TWICE? Not if I compile and run your program. Hmm ....
I get two copies when compiled and run.
Ben
Thanks for the clarification Ben. Your previous post was veery useful
also - atleast I know I'm not going mad (w.r.t to the copy constructor
being called twice :-) )
Alfonso Morra wrote: Stephan Brönnimann wrote:
2). Why is the destructor called after mc has been pushed into the vector? Because push_back creates a copy.
I dont understand the point you're making, creating a copy of a variable is not the same as deleting the variable - in other words, the fact that a copy is made of variable mc does not explain why it is fred.
Please be precise about the meaning of "deleting the variable" and
"fred".
Does it mean "the destructor of MyClass is called."
or does it mean "an object of MyClass is deleted?
3). Does the vector implementation guarantee that it will free my (contained) objects when: (i) erase() is invoked (ii) clear() is invoked (iii) vector goes out of scope?
The destructor of the "contained objects" will be called, no memory is freed by the vector except for the last case.
Once again, your response seems inconsistent. If the destructor of "contained objects" is invoked, then - memory is being freed (this is certainly true in the example I gave of contained object MyClass)
I your special case I agree, but that is because of ~MyClass()
and not because of the vector. Consider: what should happen
for std::vector<int>? Think again: How whould you store the original item in the vector? Could you provide the pseudo code for it?
If the copy construction of a class is expensive, you may use std::vector<Class*> as STL-container, however then you'll need to provide a wrapper class that takes care of copy, asssignment and destruction of the vector.
This is axiomatic. I wanted to know *what* (if any) resource management std::vector provides "out of the box", so I can decide if I need to "roll my own" resource management logic.
std::vector manages its own allocated memory, that's it.
The memory management of the vector's content is up to you.
regards, Stephan
Stephan Brönnimann wrote: Alfonso Morra wrote:
Stephan Brönnimann wrote:
2). Why is the destructor called after mc has been pushed into the vector?
Because push_back creates a copy. I dont understand the point you're making, creating a copy of a variable is not the same as deleting the variable - in other words, the fact that a copy is made of variable mc does not explain why it is fred.
Please be precise about the meaning of "deleting the variable" and "fred". Does it mean "the destructor of MyClass is called." or does it mean "an object of MyClass is deleted?
This is a typo. I meant to type "freed". By deleting the variable, I
meant any operation such as an erase, clear invokation on the vector,
that would cause an element to be deleted or erased (syntactic sugar) 3). Does the vector implementation guarantee that it will free my (contained) objects when: (i) erase() is invoked (ii) clear() is invoked (iii) vector goes out of scope?
The destructor of the "contained objects" will be called, no memory is freed by the vector except for the last case.
Once again, your response seems inconsistent. If the destructor of "contained objects" is invoked, then - memory is being freed (this is certainly true in the example I gave of contained object MyClass)
I your special case I agree, but that is because of ~MyClass() and not because of the vector. Consider: what should happen for std::vector<int>?
Please see my comment below Think again: How whould you store the original item in the vector? Could you provide the pseudo code for it?
If the copy construction of a class is expensive, you may use std::vector<Class*> as STL-container, however then you'll need to provide a wrapper class that takes care of copy, asssignment and destruction of the vector.
This is axiomatic. I wanted to know *what* (if any) resource management std::vector provides "out of the box", so I can decide if I need to "roll my own" resource management logic.
std::vector manages its own allocated memory, that's it. The memory management of the vector's content is up to you.
regards, Stephan
Alfonso Morra wrote:
Stephan Brönnimann wrote:
Alfonso Morra wrote:
Stephan Brönnimann wrote:
> 2). Why is the destructor called after mc has been pushed into the > vector?
Because push_back creates a copy.
I dont understand the point you're making, creating a copy of a variable is not the same as deleting the variable - in other words, the fact that a copy is made of variable mc does not explain why it is fred.
Please be precise about the meaning of "deleting the variable" and "fred". Does it mean "the destructor of MyClass is called." or does it mean "an object of MyClass is deleted?
This is a typo. I meant to type "freed". By deleting the variable, I meant any operation such as an erase, clear invokation on the vector, that would cause an element to be deleted or erased (syntactic sugar)
I'm not sure what you think is syntactic suger. When you request for the copntainer to remove the element, the container will call the destructor of that item, and then remove
that item from the container and then deallocate any memory required to store that item. If that item is a pointer, and you allocated memory at the end of that pointer, thats
still your responsibility.
Ben
--
I'm not just a number. To many, I'm known as a String...
Ben Pope wrote: Alfonso Morra wrote:
Stephan Brönnimann wrote:
Alfonso Morra wrote:
Stephan Brönnimann wrote:
>> 2). Why is the destructor called after mc has been pushed into the >> vector? > > > Because push_back creates a copy.
I dont understand the point you're making, creating a copy of a variable is not the same as deleting the variable - in other words, the fact that a copy is made of variable mc does not explain why it is fred.
Please be precise about the meaning of "deleting the variable" and "fred". Does it mean "the destructor of MyClass is called." or does it mean "an object of MyClass is deleted?
This is a typo. I meant to type "freed". By deleting the variable, I meant any operation such as an erase, clear invokation on the vector, that would cause an element to be deleted or erased (syntactic sugar)
I'm not sure what you think is syntactic suger. When you request for the copntainer to remove the element, the container will call the destructor of that item, and then remove that item from the container and then deallocate any memory required to store that item. If that item is a pointer, and you allocated memory at the end of that pointer, thats still your responsibility.
Ben
Thats not what I meant, (the term syntactic sugar being overloaded in
this particular usage) I was just being lazy and meant to say, the
phrases "deleting an object", "an objects destructor is called" are in
most cases, (certainly in this case) equivalent, and is largely a matter
of "syntax" (not in the computer language terminolgy sense).
In your case which deals with std::vector<MyClass>
calling ~MyClass() and to delete an allocated object of MyClass
is exactly not the same!
Just to prevent your next missunderstanding:
If you delete a pointer to an object the destructor of that object is
called.
Stephan
Stephan Brönnimann wrote: In your case which deals with std::vector<MyClass> calling ~MyClass() and to delete an allocated object of MyClass is exactly not the same!
Just to prevent your next missunderstanding: If you delete a pointer to an object the destructor of that object is called.
This is exactly what I'm saying ... Stephan
Alfonso Morra wrote: int main(int argc, char* argv[]) { MyClass mc ; std::vector<MyClass> mv ; mv.push_back(mc) ; }
Here is output from the console (code execution point is at the point where variable mc has been "pushed back" into the vector).
Default cstor called ! Copy cstor called ! Copy cstor called ! dstor called !
I have the the following questions:
1). Why is the copy constructor called TWICE? 2). Why is the destructor called after mc has been pushed into the vector?
One possibility is if your compiler's "push_back" function is
declared as taking an object by value (rather than by reference).
Then the extra creating and destruction is this local variable
in the push_back() function. You could confirm this by examining
your compiler's header files.
I can't think of any good reason why push_back would be declared
as taking the parameter by value though (mine takes it by reference),
and I don't know if this should be considered a compiler bug or not.
ISTR that compilers are allowed to make extra copies of objects
whenever they feel the need.
instead in the vector?. Storing copies rather than the original items in a vector seems quite an inefficient/expensive way of going about things
i). Object creation ii). Making a copy of the object (vector stores a copy not original) iii). Deleting the original object (so only the copy in the vector is kept) - to mimimise resource consumption
You don't need to delete the original object right away.
In your example you could use 'mc' for other things (eg. fill
out more data to it and push_back() it again).
It just dosen't seem right ... deleting an object that has just been created (purely for the purposes of making a copy) seems just plain silly ... Please say it isn't so ...
So why do you declare a temporary object and delete it a moment
later, in your assignment operator? :) This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: mjkahn |
last post by:
I've read (and read!) that you shouldn't store objects in Session variables.
I've read these reasons:
- The object takes up memory that may not be freed until the session times
out. Better to...
|
by: Alfonso Morra |
last post by:
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...
|
by: Frank Rizzo |
last post by:
In classic ASP, it was considered a bad idea to store VB6-created
objects in the Application variable for various threading issues.
What's the current wisdom on storing objects in the Application...
|
by: david |
last post by:
I have a class with some business-logic and with every roundtrip, I need
an instance of this class, so I have to create it, every time again.
That doesn't seem very efficient. I thought it would...
|
by: Miesha.James |
last post by:
Hello,
I'm trying to rewrite visual c++ code into visual c++ .NET code and
I've run across a problem with storing objects into a list.
Here;s an example of the code I have:
ref struct...
|
by: r.z. |
last post by:
I logged construtor and destructor calls for one of my classes and I
discovered that the constructor was called only once while the destructor
was called 3 times for a single object.
I have a...
|
by: Bruno.DiStefano |
last post by:
Hi All,
BACKGROUND INFO
I need to use a "vector" structure to store a number of objects that
becomes known only at run time. The constructor, at instantiation time
of a new object, increments a...
|
by: alexjcollins |
last post by:
The following program demonstrates the problem:
#include <vector>
#include <iostream>
#include <tvmet/Vector.h>
typedef tvmet::Vector<double, 3Vector3d;
class Mesh
{
|
by: DolphinDB |
last post by:
Tired of spending countless mintues downsampling your data? Look no further!
In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: Vimpel783 |
last post by:
Hello!
Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
|
by: jfyes |
last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
|
by: ArrayDB |
last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
|
by: PapaRatzi |
last post by:
Hello,
I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
|
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...
|
by: Defcon1945 |
last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
|
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...
| |