By looking at the example:
#include <iostream>
int wow=0;
class Foo{
int cow = 0;
public:
Foo(){
std::cout << "Foo +\n";
cow = 0;
++wow;
}
Foo(int n){
std::cout << "Foo has " << n << "\n";
cow = n;
++wow;
}
~Foo(){
std::cout << cow << " ~ Foo -\n";
}
void print(){
std::cout << cow << " is the foo#\n";
}
};
int main(){
void * bar = ::operator new(sizeof(Foo));
Foo * a = new(bar) Foo;
*a = Foo(10);
std::cout << wow << std::endl;
a->~Foo();
::operator delete(bar);
return 0;
}
and compiling and running it, the console shows:
Foo+
Foo has 10
10 ~ Foo -
2
10 ~ Foo -
My question is, why is the destructor called upon calling the constructor?
Should the first destructor call be 0 ~ Foo - ? Since that is the first Foo
that is overwritten by Foo(10)?
In this assignment statement
*a = Foo(10);
there is created a temporary object of the type Foo that is assigned to the object specified by the expression *a using the default copy assignment operator (neither copy or move constructor is called here). After the assignment the temporary object is deleted. The undeclared variable cow (it seems it is a data member of the class Foo) of the object pointed to by the pointer a now contains the same value 10. And in the end of the program the object pointed to by the pointer a is also deleted.
As a result you will get two messages
10 ~ Foo -
10 ~ Foo -
The first one is generated by the destructor of the temporary object and the second one is generated by the object pointed to by the pointer a.
Related
I was trying to create an object inside static function using a constructor.
Here is the code
class A {
public:
A() { this->a = 50; std::cout << "constructor called... " << this << std::endl; setAddr(this); }
~A() { this->a = 10; std::cout << "destructor called... " << this << std::endl; }
int a;
static A* addr;
static void setAddr(A* ad) { addr = ad; }
static A &create() { A(); return *addr; }
};
A* A::addr = NULL;
int main() {
A &ptr = A::create();
std::cout << "a = " << ptr.a << std::endl;
ptr.a = 100;
std::cout << "a = " << ptr.a << std::endl;
getch();
return 0;
}
I know using new is best way to do it,but i was trying to do it using contructor to know whether it can be done or not.
The output was:
constructor called... 009AF874
destructor called... 009AF874
a = 10
a = 100
Now here is my question,
1) why destructor is called when did not create an object using any declaration like A obj;
2) and if the destructor is called then how I am able to assign a value to otr.a;
By looking at the program's output I made the following conclusion.
1) I read somewhere that constructor is called after the memory has been allocated to object. And if an object is created then it has to be destroyed and the scope of the obj decided to destroy it now.
2) Since object address has previous values before destroying it and returns call return the address of the variable storing it. When I try to access it, I was able to do so because that memory address still exists.
That's not how you make a singleton. The statement
A();
creates a temporal object of class A that is destroyed (as per standard) at end of statement.
Indeed, memory is allocated before call of constructor. Resulting object can be assigned or passed by reference or value to any function of this statement, but in former case, reference is valid only until end of call expression. Exception is that if it was assigned to reference, its length of life is extended to one
of reference. After life of object ended, any access to memory it used results in UB, provided that it could be used by any other operations.
Any access to object after destructor was called is an UB as well.
Here is an example (this code intentionally contains UB)
#include <iostream>
class A {
public:
A() { this->a = 50; std::cout << "constructor called... " << this << std::endl; }
~A() { this->a = 10; std::cout << "destructor called... " << this << std::endl; }
int a;
static const A &create() {
const A& addr = A();
std::cout << "a = " << addr.a << std::endl;
return addr;
}
};
int main() {
const A &ref = A::create();
std::cout << "a = " << ref.a << std::endl;
return 0;
}
Note, that C++ allows to bind temporary only to const reference. There are way to work around that, but that's irrelevant.
Output of this program may vary, depending on compiler and level of optimization. E.g. clang with no optimization:
constructor called... 0x7ffc1f7991d0
a = 50
destructor called... 0x7ffc1f7991d0
a = 4202884
gcc may output 10 in last line. MS may crash on it. Keyword is "may", there is no rule that governs what would happen. Object stopped existing after create() returned reference to it because lifespan of addr came to end, and we are left with dangling reference.
Obviously we can extend lifespan of addr by making it static.
static const A &create() {
static const A& addr = A();
std::cout << "a = " << addr.a << std::endl;
return addr;
}
Static variable in function's scope will be created at first call of function and stops to exist when process stops.
constructor called... 0x6031b8
a = 50
a = 50
destructor called... 0x6031b8
I made the following short code to experiment and try to get a "first-hand" experience with when objects have their constructors and destructors called:
class Foo
{
public:
Foo(int bar)
{
this->bar = bar;
std::cout << "Standard constructor called" << std::endl;
}
~Foo()
{
std::cout << "Standard destructor called" << std::endl;
}
Foo(const Foo &foo)
{
std::cout << "Copy constructor called" << std::endl;
this->bar = foo.bar;
}
inline int get_bar() { return bar; }
private:
int bar;
};
Foo make_foo(int bar)
{
Foo f1(bar);
std::cout << "About to return foo with address of: " << &f1 << std::endl;
return f1;
}
int main()
{
Foo f2 = make_foo(3);
std::cout << "New variable has address of: " << &f2 << std::endl;
std::cout << "And a value of " << f2.get_bar() << std::endl;
}
But something that I find strange occurs when I run this code. Like expected, "standard constructor called" is printed and the address of foo in that function is printed. But when the function ends, no destructor is called, and f2 actually has the same memory address as f1, even though, from my understanding, f1 should have gone out of scope and had its memory freed because it was on the stack, right? Or is this not the expected outcome in this situation?
My expectation is that the copy constructor would be called for f1 to be copied to f2, and then f1 would have its destructor called and f2 would occupy a different memory address.
In case anyone is curious, this is the actual output:
Standard constructor called
About to return new foo with address of: 0x7fff518e5a88
New variable has address of: 0x7fff518e5a88
And a value of 3
Standard destructor called
Interestingly, when I change the return type of make_foo to a reference type, the function executes almost as I expect it to, with f1 being destructed and f2 copying junk data.
Is this some specific case where a variable on the stack will not have its memory freed when it's being returned to be assigned to another variable that I should be aware of?
The compiler is performing a return value optimization (RVO). You can read about it here:
https://en.wikipedia.org/wiki/Copy_elision#Return_value_optimization
Helo, I'm new to C++ programming.
I'm not understanding about these line of code...
SomeClass someClassObject(35);
...
someClassObject = SomeClass(46);
first of all,what does "someClassObject = SomeClass(46)" does? Is it like what pointer of SomeClass E.G.: "someClassObject = new SomeClass(46)" does but on stack?
No pointers are involved here. SomeClass(46) constructs a temporary object, typically on the stack. This is followed by an assignment to the variable someClassObject. The exact semantics of this assignment can be user-defined by overloading the assignment operator.
PS: Note the missing semicolons at the end of your statements.
SomeClass(46) constructs a new instance of SomeClass on the stack, by calling the constructor passing the number 46 to it.
someClassObject = some instance of SomeClass call the operator= on someClassObject.
Unless the constructor is declared explicit it could also have been written as:
someClassObject = 46;
Take a look at this example: http://ideone.com/7kgWob pasted below:
#include <iostream>
using namespace std;
class SomeClass
{
private:
int i = 0;
public:
SomeClass() { cout << "default constructor\n"; };
SomeClass(int val) { i = val; cout << "constructor getting int: " << val << '\n'; };
~SomeClass() { cout << "destrucing object having i: " << i << '\n'; };
SomeClass& operator=(const SomeClass& rhs) {
cout << "operator= getting int: " << rhs.i << '\n';
if (this != &rhs) {
i = rhs.i;
}
return *this;
}
};
int main() {
SomeClass a(10);
SomeClass b = SomeClass(20);
SomeClass c(35);
c = SomeClass(46);
return 0;
}
It will output:
constructor getting int: 10
constructor getting int: 20
constructor getting int: 35
constructor getting int: 46
operator= getting int: 46
destrucing object having i: 46
destrucing object having i: 46
destrucing object having i: 20
destrucing object having i: 10
In essence it creates a temporary instance, and sets the current instance to the same value as the temporary (two objects with the same value exists at this point). It then frees the temporary. Since no new is involved it happens on the stack.
SomeClass* someClassObject = new SomeClass(46); you initialized a pointer of type class SomeClass to a dynamic object through calling the constructor that takes an integer.
the second you called the overloaded assignment operator which calls the constructor that takes an integer creating a temporary object thenn assigns it to someClassObject.
don't forget ; it is not arbitrary.
I have a function which returns an object by value. The recipient variable requires the outward conversion operator on that object to be called.
If I construct the returned object at the return statement (RVO) its destructor gets called before the outward conversion operator.
However, if I name the object, and return that, the outward conversion operator gets called before the object is destructed.
Why is that?
#include <iostream>
class Ref {
public:
Ref(int * ptr) : iptr(ptr) {
std::cout << "Ref Constructed at: " << long(this) << " Pointing to: " << long(ptr) << '\n';
}
Ref(Ref & ref) : iptr(ref) {
std::cout << "Ref Moved to: " << long(this) << '\n';
ref.iptr = nullptr;
}
operator int () {
std::cout << "Ref-To int: Temp at: " << long(iptr) << '\n';
return *iptr;
}
operator int* () {
std::cout << "Ref-To int*: Temp at: " << long(iptr) << '\n';
return iptr;
}
~Ref() {
delete iptr;
std::cout << "Ref at: " << long(this) << " Deleted: " << long(iptr) << '\n';
}
private:
int * iptr;
};
Ref foo() {
int * temp = new int(5);
Ref retVal(temp);
std::cout << "Return named Ref\n";
return retVal;
}
Ref bar() {
int * temp = new int(5);
std::cout << "Return anonymous Ref\n";
return Ref(temp);
}
int _tmain(int argc, _TCHAR* argv[])
{
std::cout << "********* Call foo() *************\n";
int result = foo();
std::cout << "\n********* Call bar() *************\n";
int result2 = bar();
return 0;
}
Output from this is:
********* Call foo() *************
Ref Constructed at: 2356880 Pointing to: 5470024
Return named Ref
Ref-To int*: Temp at: 5470024
Ref Moved to: 2356956
Ref at: 2356880 Deleted: 0
Ref-To int: Temp at: 5470024
Ref at: 2356956 Deleted: 5470024
********* Call bar() *************
Return anonymous Ref
Ref Constructed at: 2356680 Pointing to: 5470024
Ref-To int*: Temp at: 5470024
Ref Constructed at: 2356968 Pointing to: 5470024
Ref at: 2356680 Deleted: 5470024
Ref-To int: Temp at: 5470024
Press any key to continue . . .
When bar() is called the reference is deleted before the conversion operator is called, and it crashes.
Also, I don't understand why the Ref to int* conversion is getting called when the return value is being built.
What is going on
I don't understand why the Ref to int* conversion is getting called when the return value is being built.
That happens because, apparently, MSVC does not perform RVO in debug mode, so the "copy constructor" (Ref(Ref&)) gets called to return from the foo function and this gets executed:
Ref(Ref & ref) : iptr(ref) {
// ...
}
where iptr, of type int*, is initialized with the implicit conversion from ref.
As #bogdan made me notice, this "copy constructor" of yours really has a move constructor semantic, and you should probably write a specific Ref(Ref&&) for that instead.
In bar, we have that you are building an rvalue return Ref(temp) which cannot be bound to a lvalue reference for the Ref(Ref&) constructor, and therefore the other constructor is picked and the pointer in copied in (without resetting the temporary one).
When the temporary one gets out of scope, the pointer is deleted, and when the constructed object from bar also goes out of scope, the same pointer is deleted, causing undefined behaviour (which is the reason of your crash).
The C++ way to write that class
Your class has many other issues. For one it can lead to various crashes and it's generally not memory safe. In C++ you would write something like this for that class:
class Ref {
public:
explicit Ref(std::unique_ptr<int> ptr)
: iptr(std::move(ptr))
{}
int get() const { return *iptr; }
int* data() const { return iptr.get(); }
private:
std::unique_ptr<int> iptr;
};
or even just std::unique_ptr.
The point here is that implicit conversions and manual dynamic memory allocation will often lead to many bugs and "crashes". Avoid them like the plague as much as possible.
I am trying to learn C++ and from what I've read in books and on SO:
If I use auto x = new Object(); x is a pointer to address of Object and this is in dynamic memory and exists until I delete it.
However if I use Object x; or auto x = Object() it only lasts until it goes out of scope.
In an example they have shown this:
void foo()
{
Point p = Point(0,0);
} // p is now destroyed.
What I don't understand is what happens when I return a object when I don't use new? Will it be a copy of the object?
Here is an example of what I am not sure about:
class Object
{
public:
int X;
static Object Foo(int y)
{
Object result;
result.X = y;
return result;
}
};
class TestContainer
{
public:
void Run()
{
for(auto i = 0; i < 10; i++)
{
_objects.at(i) = Object::Foo(i + (rand() % 10 + 1));
}
}
private:
std::vector<Object> _objects;
};
void main()
{
TestContainer tc;
while(true)
{
tc.Run();
}
}
Note I haven't tested this code but I think it illiterates my confusion. In my main function I instantiate TestContainer and endless call it's Run method. This in turn loops calling a static Foo method on Object that returns a copy of a new Object, which is stored in a vector.
My question is, what happens with all the Object's? If I replace element 2 in the objects vector with a new Object, is the old value now "out of scope" and is deleted?
Will it be a copy of the object?
Yes.
Or a move could be used instead, or the entire thing could be optimised away to produce only one actual object in your final, compiled program.
But, basically, yes.
If I replace element 2 in the objects vector with a new Object, is the old value now "out of scope" and is deleted?
Yes.
As an aside, you're using at on elements that don't exist; to add elements, use insert or push_back.
A simple class like this behaves much like a POD variable. o1=o2 copies the fields, element-wise. So the target Object of an assignment does not get deleted but overwritten.
Objects which go out of scope "go away" (because the stack is unwound) like e.g. an int.
Here is a run-able example that I believe illustrates this behavior:
#include <iostream>
using namespace std;
class Foo {
private:
int id;
public:
Foo(int x)
: id(x)
{
cout << this->id << " is created" << endl;
}
Foo(const Foo& rhs)
: id(rhs.id)
{
cout << "copied " << this->id << endl;
}
Foo& operator=(Foo rhs){
this->id=rhs.id;
cout << "assigned " << this->id << endl;
return *this;
}
~Foo(){
cout << this->id << " is destroyed" << endl;
}
int getID(){
return this->id;
}
};
Foo bar(){
Foo f1 = Foo(1);
cout << f1.getID() << " from bar" << endl;
return f1;
}
int main(){
Foo f2 = bar();
cout << f2.getID() << " from main" << endl;
return 0;
}
This produces this output:
1 is created
1 from bar
1 from main
1 is destroyed
From this, I'm not seeing a copy or an assignment. I suspect what is happening is that both f1 and f2 are referencing the same instance of the object in memory. The object is not being de-allocated when the f1 reference goes out of scope because the object has another reference assigned to it.