Apologies if the question sounds silly, I was following experts in SO and trying some examples myself, and this is one of them. I did try the search option but didn't find an answer for this kind.
class A
{
public:
A(){cout<<"A Contruction"<<endl;}
~A(){cout<<"A destruction"<<endl;}
};
int main()
{
vector<A> t;
t.push_back(A()); // After this line, when the scope of the object is lost.
}
Why is the destructor of the class called twice ?
To add the element a copy constructor is invoked on a temporary object. After the push_back() the temporary object is destroyed - that't the first destructor call. Then vector instance goes out of scope and destroys all the elements stored - that's the second destructor call.
This will show you what's happening:
struct A {
A() { cout << "contruction\n"; }
A(A const& other) { cout << "copy construction\n"; }
~A() { cout << "destruction\n"; }
};
int main() {
vector<A> t;
t.push_back(A());
}
The destructor is called once when the temporary sent to push_back is destroyed and once when the element in t is destroyed.
There are two destructor calls because there are two objects: the argument to push_back, and the newly added element within vector t.
STL containers store copies. In your example the element added to the vector by push_back is copy constructed from the argument passed to push_back. The argument is A(), which is a temporary object, see here (variant 4).
Expanding the answer a bit, altough you havent explicitely asked for it: It might be useful to know when the temporary is destroyed. The standard (N4140) sais it pretty clearly in 12.2 p3:
... Temporary objects are destroyed as the last step in evaluating the
full-expression (1.9) that (lexically) contains the point where they
were created...
Side note: If you use emplace_back there is only one object. The new element in the container is directly constructed from the arguments to emplace_back. Many STL container learned an emplace variant in C++11.
Most probably, copy of your object is getting created. Because of which, the destructor for the copied-object, and for the original-object makes the call-count=2.
Example: Even though, you are passing the object reference, to some class, this internally would invoke the copy-constructor. To avoid this, the child-class (to which you are passing the parent reference, must be as;
Parent *const &p parentRef; //Child.h
Then, the parent object will be passed as;
// Parent.cpp
Parent *parentObj = this;
Child *childObj = Child(parentObj);
Additionally, you can debug the copy-constructor invokation, by overriding;
Parent(const Parent& object){
cout <<"copy called.." << endl;
}
...
More info #stackoverflow#
Related
Have looked at various similar questions here but still can't figure out why the following code does not compile:
// these three are defined somewhere
class A;
std::unique_ptr<A> make_a();
void take_a(std::unique_ptr<A>&&);
int main(){
take_a(make_a()); // this fails
return 0;
}
According to this:
If the default deleter is used, T must be complete at the point in
code where the deleter is invoked, which happens in the destructor,
move assignment operator, and reset member function of
std::unique_ptr.
As far as I understand, none of these (destructor, move assignment operator, nor reset member function) happens in main.
So why does compiler needs the definition of A here?
Since main has a unique_ptr within its scope, realistically it would need to know how to delete the object it holds.
It's possible that take_a doesn't actually take ownership of the object, thus main would need to delete.
main gets a temporary unique_ptr from make_a(), let's call it X. It then passes an rvalue reference to X to take_a. It still has the destroy X. Hence, it has to call the destructor after take_a, even though X would typically be empty at that point.
We need class A description (at least constructor and destructor) in order to create and move std::unique_ptr<A> objects; take_a(make_a()) is creating such object because make_a() is pass-by-value. It first creates a new unique_ptr<A> object, initialize it (using default constructor), and then update its value and returns this new object. Here the default constructor/destructor is being used, which the compiler is unable to find.
#include <bits/stdc++.h>
class A {
public: A() {}
public: ~A() {}
};
std::unique_ptr<A> make_a() {
std::cout << "make";
std::unique_ptr <A> tt = nullptr;
return tt;
}
void take_a(std::unique_ptr<A>&&) {
std::cout << "take";
}
int main(){
take_a(make_a()); // this works now
return 0;
}
Edit: Forgot to add the link. Works the other way too.
I am struggling a little bit with move semantics. I read a lot about that topic, however, there are two concrete problems to which I did not found any answers and, thus, like to present them to you.
First, I have the following exemplary code:
#include <iostream>
#include <cstddef>
class A
{
public:
A *ptr;
virtual ~A()
{
std::cout << "dtor" << std::endl;
delete ptr;
ptr=nullptr;
}
};
main()
{
A x, y;
x.ptr = &y;
}
// compile and link like this with g++: g++ -std=c++0x -lstdc++ code.cc
Class A is able to have a member of itself. I use this "composite pattern" concept to build a hierarchy. However, in this case, when object x is destructed, its destructor deletes the pointer to object y. When finally object y should be destructed, it is already which yields an error... How can I solve this?
The second case looks like this:
main()
{
A x, y;
y = std::move(x);
std::cout << "x.ptr: " << x.ptr << std::endl;
std::cout << "y.ptr: " << y.ptr << std::endl;
}
Here, I can see that both references are equal which means both exists. I though that std::move moves the content from x to y. I would have expected that x.ptr is "empty"....?
Thanks in advance!
Cheers
In the first case, both of your x and y objects are created on stack so they will be destructed automatically. However, your class A's destructor uses delete which assumes that the object referred by ptr was created on heap with new.
So it's an error to set x.ptr to refer an object created on stack (like y). A correct code would be
x.ptr = new A;
This is the danger of raw pointers - you can't differentiate between pointers to dynamically allocated objects (that you have to eventually delete) and "just pointers" (that you can't).
It's better if you use std::unique_ptr<A> instead of raw pointer A*.
It will also call delete my itself, so your delete ptr won't be needed.
As for the second case, for primitive types move is actually just a copy. If you move from int to int, or from ptr to ptr, it's just a copy as there is nothing to optimize with move for primitive types, there is no special "emptying" of the moved-from object. But for your case there are good things called smart pointers that actually do "emptying" (because it guarantees correctness). You guessed it - I'm talking about std::unique_ptr.
So again, if you change your ptr from A* to std::unique_ptr<A> then move will do the job you're looking for.
In two words, std::unique_ptr is your real friend here.
In the first, you create two objects of type A on the stack
A x,y;
then assign the address of y to the member x.ptr. When the objects go out of scope, their destructors are called. This happens in the reverse order of their construction, so it should be
y.~A()
x.~A()
In your case, you manually call delete in the destructor, and this will call delete on an already deleted object when execution x.~A().
This not the only problem in your code:
You call delete on an object on the stack. Calls to deletes should be matched by calls to new. Even better, you should manually call new or delete and use std::unique_ptr and std::shared_ptr`.
When b's destructor is called it will delete ptr which uses an uninitialized value for ptr. The compiler-generated constructor does not initialize the ptr tp nullptr. I know at least one compiler which does this in debug mode but in release mode.
When you use std::move, it will finally call the move constructor (or move assignmnet operator). Since you did not define one manually but you define a destructor, there will be no compiler-generated move constructor. So in your case, it will eventually call the implicit copy-constructor and copy the member values, which is what you are seeing.
Even if you add
class A
{
public:
A(A&& a) = default;
A& operator=(A&& a) = default;
A *ptr;
virtual ~A()
{
std::cout << "dtor" << std::endl;
delete ptr;
ptr=nullptr;
}
};
to request compiler-generated move semantics, it will generate code that does a member-wise move, looking like
A(A&& a): ptr( std::move(a.ptr) ) {}
For a pointer type, this just assigns the value to the new variable and leaves the old variable as is. The standard's requirements on a moved object are quite basic and fulfilled by this.
I have class like this
class variable
{
public:
variable(int _type=0) : type(_type), value(NULL), on_pop(NULL)
{
}
virtual ~variable()
{
if (type)
{
std::cout << "Variable Deleted" <<std::endl;
on_pop(*this);
value=NULL;
}
}
int type;
void* value;
typedef void(*func1)(variable&);
func1 on_pop;
}
And then I push instances into a std::vector like this:
stack.push_back(variable(0));
I expect that the destructor of variable will be called but the if won't enter until a value is assigned to type because I expect the constructor I provide will be called when the instance is copied into the vector. But for some reason it is not.
After calling stack.push_back the destructor (of the copy?) is ran and type has some random value like if the constructor was never called.
I can't seem to figure what I am doing wrong. Please help! ^_^
EDIT:
Ok here is a self contained example to show what I mean:
#include <iostream>
#include <vector>
class variable
{
public:
variable(int _type=0) : type(_type), value(NULL), on_pop(NULL)
{
}
~variable()
{
if (type)
{
std::cout << "Variable Deleted" <<std::endl;
on_pop(*this);
value=NULL;
}
}
int type;
void* value;
typedef void(*func1)(variable&);
func1 on_pop;
};
static void pop_int(variable& var)
{
delete (int*)var.value;
}
static void push_int(variable& var)
{
var.type = 1;
var.value = new int;
var.on_pop = &pop_int;
}
typedef void(*func1)(variable&);
func1 push = &push_int;
int main()
{
std::vector<variable> stack;
stack.push_back(variable(0));
push(stack[stack.size()-1]);
stack.push_back(variable(0));
push(stack[stack.size()-1]);
stack.push_back(variable(0));
push(stack[stack.size()-1]);
return 0;
}
The program above outputs the following:
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted
Process returned 0 (0x0) execution time : 0.602 s
Press any key to continue.
Welcome to RVO and NRVO. This basically means that the compiler can skip creating an object if it's redundant- even if it's constructor and destructor have side effects. You cannot depend on an object which is immediately copied or moved to actually exist.
Edit: The actual value in the vector cannot be ellided at all. Only the intermediate variable variable(0) can be ellided. The object in the vector must still be constructed and destructed as usual. These rules only apply to temporaries.
Edit: Why are you writing your own resource management class? You could simply use unique_ptr with a custom deleter. And your own RTTI?
Every object that was destructed must have been constructed. There is no rule in the Standard that violates this. RVO and NRVO only become problematic when you start, e.g., modifying globals in your constructors/destructors. Else, they have no impact on the correctness of the program. That's why they're Standard. You must be doing something else wrong.
Ultimately, I'm just not sure exactly WTF is happening to you and why it's not working or what "working" should be. Post an SSCCE.
Edit: In light of your SSCCE, then absolutely nothing is going wrong whatsoever. This is entirely expected behaviour. You have not respected the Rule of Three- that is, you destroy the resource in your destructor but make no efforts to ensure that you actually own the resource in question. Your compiler-generated copy constructor is blowing up your logic. You must read about the Rule of Three, copy and swap and similar idioms for resource handling in C++, and preferably, use a smart pointer which is already provided as Standard like unique_ptr which does not have these problems.
After all, you create six instances of variable- three temporaries on the stack, and three inside the vector. All of these have their destructors called. The problem is that you never considered the copy operation or what copying would do or what would happen to these temporaries (hint: they get destructed).
Consider the equal example of
int main()
{
variable v(0);
push_int(v);
variable v2 = v;
return 0;
}
Variable v is constructed and allocates a new int and everything is dandy. But wait- then we copy it into v2. The compiler-generated constructor copies all the bits over. Then both v2 and v are destroyed- but they both point to the same resource because they both hold the same pointer. Double delete abounds.
You must define copy (shared ownership - std::shared_ptr) or move (unique ownership - std::unique_ptr) semantics.
Edit: Just a quick note. I observe that you actually don't push into items until after they're already in the vector. However, the same effect is observed when the vector must resize when you add additional elements and the fundamental cause is the same.
The destructor is called 6 times. A constructor is called six times. Just not the one you intended.
Ok. I've been reading some more about the intrinsics of different containers and, apparently, the one that does the job I'm trying to accomplish here is std::deque.
here is my c++ code :
class Sample
{
public:
int *ptr;
Sample(int i)
{
ptr = new int(i);
}
~Sample()
{
delete ptr;
}
void PrintVal()
{
cout << "The value is " << *ptr;
}
};
void SomeFunc(Sample x)
{
cout << "Say i am in someFunc " << endl;
}
int main()
{
Sample s1= 10;
SomeFunc(s1);
s1.PrintVal();
}
it returns me the output like :
Say i am in someFunc
Null pointer assignment(Run-time error)
here As the object is passed by value to SomeFunc the destructor of the object is called when the control returns from the function
should i right ? if yes then why it is happening ? and whats the solution for this ???
Sample is passed by value to SomeFunc, which means a copy is made. The copy has the same ptr, so when that copy is destroyed when SomeFunc returns, ptr is deleted for both objects. Then when you call PrintVal() in main you dereference this invalid pointer. This is undefined behavior. Even if that works then when s1 is destroyed ptr is deleted again, which is also UB.
Also, if the compiler fails to elide the copy in Sample s1= 10; then s1 won't even be valid to begin with, because when the temporary is destroyed the pointer will be deleted. Most compilers do avoid this copy though.
You need to either implement copying correctly or disallow copying. The default copy-ctor is not correct for this type. I would recommend either making this type a value type (which holds its members directly rather than by pointer) so that the default copy-ctor works, or use a smart pointer to hold the reference so that it can manage the by-reference resources for you and the default copy-ctor will still work.
One of the things I really like about C++ is that it's really friendly toward using value types everywhere, and if you need a reference type you can just wrap any value type up in a smart pointer. I think this is much nicer than other languages that have primitive types with value semantics but then user defined types have reference semantics by default.
You usually need to obey the Rule of Three since you have an pointer member.
In your code example to avoid the Undefined Behavior you are seeing:
Replace the need to in first statement by must.
Since SomeFunc() takes its argument by value, the Sample object that you pass to it is copied. When SomeFunc() returns, the temporary copy is destroyed.
Since Sample has no copy constructor defined, its compiler-generated copy constructor simply copies the pointer value, so both Sample instances point to the same int. When one Sample (the temporary copy) is destroyed, that int is deleted, and then when the second Sample (the original) is destroyed, it tries to delete the same int again. That's why your program crashes.
You can change SomeFunc() to take a reference instead, avoiding the temporary copy:
void someFunc(Sample const &x)
and/or you can define a copy constructor for Sample which allocates a new int rather than just copying the pointer to the existing one.
When you pass the argument for the function it's called the copy constructor, but you don't have one so the pointer is not initialised. When it exits the function, the object is calls the destructor to delete the unitialised pointer, so it thows an error.
Instead of
int main()
{
Sample s1= 10;
SomeFunc(s1);
s1.PrintVal();
}
try to use
int main()
{
Sample* s1= new Sample(10);
SomeFunc(*s1);
s1->PrintVal();
}
I have a Foo object, and a std::list holding instances of it. My problem is that when I add a new instance to the list, it first calls the ctor but then also the dtor. And then the dtor on another instance (according to the this pointer).
A single instance is added to the list but since its dtor (along with its parents) is called, the object cant be used as expected.
Heres some simplified code to illustrate the problem:
#include <iostream>
#include <list>
class Foo
{
public:
Foo()
{
int breakpoint = 0;
}
~Foo()
{
int breakpoint = 0;
}
};
int main()
{
std::list<Foo> li;
li.push_back(Foo());
}
When you push_back() your Foo object, the object is copied to the list's internal data structures, therefore the Dtor and the Ctor of another instance are called.
All standard STL container types in C++ take their items by value, therefore copying them as needed. For example, whenever a vector needs to grow, it is possible that all values in the vector get copied.
Maybe you want to store pointers instead of objects in the list. By doing that, only the pointers get copied instead of the object. But, by doing so, you have to make sure to delete the objects once you are done:
for (std::list<Foo*>::iterator it = list.begin(); it != list.end(); ++it) {
delete *it;
}
list.clear();
Alternatively, you can try to use some kind of 'smart pointer' class, for example from the Boost libraries.
You are creating a temporary Foo here:
li.push_back( Foo() )
push_back copies that Foo into its internal data structures. The temporary Foo is destroyed after push_back has been executed, which will call the destructor.
You will need a proper copy constructor that increases some reference count on the class members that you do not want to destroy early -- or make it private to force yourself on the pointer solution.
Use this object to understand:
class Foo
{
public:
Foo(int x): m_x(x)
{
std::cout << "Constructed Object: " << m_x << ")\n";
}
Foo(Foo const& c): m_x(c.m_x+100)
{
std::cout << "Copied Object: " << m_x << ")\n";
}
~Foo()
{
std::cout << "Destroyed Object: " << m_x << ")\n";
}
};
The First main
std::list<Foo*> li;
li.push_back(Foo(1));
Here we create a temporary Foo object and call push_back(). The temporary object gets copied into the list and the function returns. On completion of this statement the temporary object is then destroyed (via the destructor). When the list is destroyed it will also destroy all the obejcts it contains (Foo is an object with a destructor so destruction includes calling the destructor).
So you should see somthing like this:
Constructed Object: 1
Constructed Object: 101
DestroyedObject: 1
DestroyedObject: 101
In the second example you have:
std::list<Foo*> li;
li.push_back(new Foo(1));
Here you dynamically create an object on the heap. Then call the push_back(). Here the pointer is copied into the list (the pointer has no constructor/destructor) so nothing else happens. The list now contains a pointer to the object on the heap. When the function returns nothing else is done. When the list is destroyed it destroys (note the subtle difference betweens destroy and delete) the object it contains (a pointer) but a pointer has no destructor so nothing happens any you will leak memory.
So you should see somthing like this:
Constructed Object: 1
What actually happens here is that you store a copy of the passed object in the list, because you're sending it by value instead of by reference. So the first dtor that is called is actually called on the object you pass to the push_back method, but a new instance had been created by then and it is now stored in the list.
If you don't want a copy of the Foo object to be created, store pointers to Foo objects in the list instead of the objects themselves. Of course when doing it you will have to properly release memory on destruction of the list.
Making the list holding pointers instead of instances solves the problem with the destructor being called. But I still want to understand why it happens.
#include <iostream>
#include <list>
class Foo
{
public:
Foo()
{
int breakpoint = 0;
}
~Foo()
{
int breakpoint = 0;
}
};
int main()
{
std::list<Foo*> li;
li.push_back(new Foo());
}