Consider the following piece of code:
struct foo {
std::string id;
};
int main() {
std::vector<foo> v;
{
foo tmp;
v.push_back(std::move(tmp));
}
}
LIVE DEMO
In the piece of code demonstrated:
The default constructor of class foo is going to be invoked for the construction of object tmp.
The move constructor of class foo is going to be invoked in the statement v.push_back(std::move(tmp));.
The destructor of class foo is going to be invoked twice.
Questions:
Why the destructor of a moved from object is called twice?
What is moved from the object that is being moved really?
Why the destructor of a moved object is called twice?
The first destructor destroys the moved-from tmp when it goes out of scope at the first } in main(). The second destructor destroys the move-constructed foo that you push_back'd into v at the end of main() when v goes out of scope.
What is moved from the object that is being moved really?
The compiler-generated move constructor move-constructs id, which is a std::string. A move constructor of std::string typically takes ownership of the block of memory in the moved-from object storing the actual string, and sets the moved-from object to a valid but unspecified state (in practice, likely an empty string).
Related
Does a destructor gets called before an object is destroyed or after an object is destroyed?
I think that it is called before an object is destroyed because after an object is destroyed we cant access that memory to free any resource in there but if I am wrong then please correct me so I can understand it well
#include <iostream>
#include <cassert>
#include <cstddef>
class Check
{
public:
int neu{};
Check() = default;
Check(int n)
{
neu = n;
}
void print()
{
std::cout << neu << std::endl;
}
~Check()
{
std::cout << "It has been destroyed "<<neu <<std::endl;
}
};
int main()
{
Check let,see(30);
let.print();
return 0;
// does destructor gets called here
} // or does destructor gets called herecode here
Does a destructor gets called before an object is destroyed or after an object is destroyed?
The lifetime of the object has ended when the destructor is called. The object is destroyed by the destructor.
// does destructor gets called here
} // or does destructor gets called herecode here
There's really no practical difference.
The automatic objects are alive within the block and they aren't alive outside the block. The objects are destroyed when the block is exited. As such, it is reasonable to say that they are destroyed at the point where the closing brace is.
From ISO standard (Special member functions - Destructors):
Once a destructor is invoked for an object, the object no longer
exists; the behavior is undefined if the destructor is invoked for an
object whose lifetime has ended.
Destructor call is essentially description of actions need to consider object destroyed. Destructor can be called explicitly, it results in end of life for that object. Explicit calls are rare, usually done for objects created by placement new.
Given the example provided, the question is actually about order of destructor calls. The destructors for sub-objects ( base class-type included, if any present) are called after. So you can safely access them until exit from destructor. Order of call is based on declaration order, just like order of initialization but inverted. Subobject of base-class type is considered the first for initialization and the last for destruction.
I was preparing lecture on copy constructor and found this:
MyClass myFunction()
{
MyClass mc;
return mc;
}
the statement says:
If we call myFunction, then C++ will create a new myClass object
that's initialized to mc when myFunction returns. Thus while your code
might act like it's transparently moving the object from inside of
myFunction to the rest of your code, it's actually making a temporary
copy.
I think statement MyClass mc; will create the object and it returned form function not any temporary object.
Where am I going wrong? Can somebody elaborate the statement to be able to understand easily?
I think statement MyClass mc; will create the object
Correct.
and it returned form function not any temporary object.
I don't fully understand your statement, so I cannot tell whether you've gone wrong, but this is what happens:
mc is a local variable. Local variables are destroyed when the function exits. Before it is destroyed, a temporary object is copy-initialized from it. The temporary object is then returned from the function.
Extra knowledge 1: Since C++11, the temporary is copy-initialized by move, if possible.
Extra knowledge 2: Standard explicitly allows the compiler to skip the copy/move and instead construct the object at the call site. This optimization is known as (named) return value optimization and is a form of copy elision. Despite this, you can not return objects that are neither copyable nor movable. That is because an implementation of C++ is not required to do NRVO.
Let's say you have this code:
#include <iostream>
using namespace std;
class MyClass
{
public:
int *v;
MyClass()
{
v=new int[5];
for(int i=0;i<5;i++) v[i]=i; // x will look like : 0,1,2,3,4
}
~MyClass()
{
cout<<"Destructor called! Now v is deallocated! \n";
delete[] v;
}
};
MyClass myFunction()
{
MyClass mc;
return mc;
}
int main()
{
MyClass x;
x=myFunction();
cout<<x.v[2]<<'\n'; //it may or may not print the right thing
return 0;
}
As you can see, myFunction returns the object mc like you said. But you also know that the destructor of mc will be called when mc goes out of scope - mc is declared inside myFunction, so the destructor will be called after the function is executed and memory will be freed (delete[] v). The memory is deallocated, but the values are still there in the memory! So, even though x=myFunction(); will work, you will have an object where the memory v points to is deallocated! So, cout<<x.v[2]<<'\n'; may not print the right thing. If you compile the code it will probably print the correct value (2), because the memory was not overwritten, but if you would do some more allocations before the cout statement, or after some time of using your OS, you will see that the value printed is incorrect/crash as the memory will be overwritten by other programs. v still points to that memory block, but it doesn't know what's there because the memory is deallocated.
Inside myFunction: v -> |0|1| 2 |3|4|...
After exiting myFunction: v -> |0|1| 2 |3|4|.....
After some memory allocations: v -> |a|1| b |#|%|3|7|2|1|*|!|......
For a simple class like this:
class X {
public:
//...
private:
int *ptr;
};
X::~X() {
delete ptr;
}
I have written a destructor to free the memory pointed to by ptr. Now, I am wondering, if my destructor stays like this, when is ptr actually destroyed?
Thanks
I think this article might answer most of your questions
"Destructors are implicitly called when an automatic object (a local
object that has been declared auto or register, or not declared as
static or extern) or temporary object passes out of scope. They are
implicitly called at program termination for constructed external and
static objects. Destructors are invoked when you use the delete
operator for objects created with the new operator."
More specifically:
"The destructors of base classes and members are called in the reverse
order of the completion of their constructor:
The destructor for a class object is called before destructors for
members and bases are called.
Destructors for nonstatic members are called before destructors for
base classes are called.
Destructors for nonvirtual base classes are called before destructors
for virtual base classes are called."
delete invokes the destructor of the object that is being deleted and then frees the memory it occupied.
The destructor will calls in the end of scope where the specific instance are.
The local version of ptr for a given instance of X will be destroyed when the object goes out of scope. For example:
int main()
{
X obj;
for (int i=0; i<10; i++) {
X tmp;
// do work with tmp
...
// tmp goes out of scope here
// the destructor tmp::~X will be called here, immediately after each iteration ends
}
// obj goes out of scope here
// the destructor obj::~X called when the program ends
}
I had to polish up my understanding of the circumstances under which constructors are called. During this I stumbled over this example from Microsoft:
//RVO class is defined above in figure 4
#include <stdio.h>
RVO MyMethod (int i)
{
RVO rvo;
rvo.mem_var = i;
throw "I am throwing an exception!";
return (rvo);
}
int main()
{
RVO rvo;
try
{
rvo=MyMethod(5);
}
catch (char* str)
{
printf ("I caught the exception\n");
}
}
The RVO class simply has constructor, copyconsdtuctor and destructor print when they are called. Microsoft states that with thorw commented out and no NRVO the output will be:
I am in constructor
I am in constructor
I am in copy constructor
I am in destructor
I am in destructor
I am in destructor
However I can't quite follow. I think that this is what happens:
In main constructor is called for RVO rvo;
In MyMethod constructor is called for RVO rvo;
For return (rvo); the copyconstructor is called
In MyMethod destructor is called for the local RVO
In Main destructor is called for the local rvo
This leaves me with one less destructor call than microsoft proclaims. What am i missing?
For completness the RVO class:
class RVO
{
public:
RVO(){printf("I am in constructor\n");}
RVO (const RVO& c_RVO) {printf ("I am in copy constructor\n");}
~RVO(){printf ("I am in destructor\n");}
int mem_var;
};
if you look carefully at the statement rvo=MyMethod(5);
rvo is assigned by the return object of MyMethod, the return object should be constructed in the scope of the main function. This object is unnamed and is a temporary object. the constructor of such an object is shown in the output that is not obvious on first look.
Don't be confused. Without return-value optimization, three) objects are created (including the temporary used for copying via copy constructor), and therefore three objects are being destroyed (including the temporary once again), so it's all good.
With RVO though, the temporary will not be created while copying (the object will be created in the caller's stack frame directly), and you will see only two constructions and two destructions.
rvo is constructed in main()
rvo is constructed in MyMethod
a unnamed RVO-object is copy-constructed from the rvo in MyMethod by the return statement
all three objects are destroyed
"In main constructor is called for RVO rvo; In MyMethod constructor is called for RVO rvo; For return (rvo); the copyconstructor"
So three objects are constructed, in normal circumstances there should be three destroyed. The returned value also needs to be destructed.
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#