C++ operator overloading constructor - c++

Can some one explain how below program becomes infinte loop of "AabAabAab.."
#include "stdafx.h"
#include <iostream>
using namespace std;
class Base {
public:
Base(int j=1):i(j)
{cout<<"B";}
private:
int i;
};
class Case{
public:
Case(int j=1):i(j) {cout<<"A";}
operator Base() { cout<<"ab"; return *(new Case); }
private:
int i;
};
int main()
{
Base obj = Case();
return 0;
}

Base obj = Case();
This calls the Case default constructor, printing A. Then, there is a conversion to Base via this operator, which has an infinite recursion:
operator Base() { cout<<"ab"; return *(new Case); }
Because it attempts to return a Case instance (prints abA), which must be converted to Base, which invokes the conversion operator, which creates a Case instance (prints abA), which must be converter to Base, which...

Can some one explain how below program becomes infinte loop of "AabAabAab.."
Not really infinite. This will eventually crash your program because of stack overflow. This is what's going on. Here:
Base obj = Case();
You are creating a temporary object of type Case and using it to initialize an object of type Base.
The only way this can be done is by picking the user-defined conversion operator of Case, which can return a Base.
Now this conversion operator in turn happens to create a temporary object of type Case, from which the return value of the operator should be initialized.:
return *(new Case);
Since the return value is itself of type Base, the temporary now has to be converted to an object of type Base - and since the temporary has type Case, the same user-defined conversion operator is invoked again.
This is what attempts to generate an infinite recursion. Since each function call requires creating a stack frame, however, your neverending recursion will eventually cause a stack overflow, and your process will be terminated.

Related

C++ another unique_ptr incomplete type question

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.

Constructor behavior in case of default, parameterized, copy ctor and assignment operator

I was going through Thinking in C++ and have some confusion regarding the behaviors of constructors in C++. Here is my sample code:
#include<iostream>
using namespace std;
class base
{
public:
int a;
/*Ctor 1*/ base() { cout<<" default"<<endl; }
/*Ctor 2*/ base(int a){ cout<<" base::int "<<endl; }
/*Ctor 3*/ base(const base& b) { cout<<" base::cc "<<endl; }
/*Asgn 1*/ base operator=(base b){
cout<<" base::assignment - base"<<endl;
return b;
}
/*Asgn 2*/ /* base operator=(int b){
cout<<" base::assignment - int"<<endl;
return (base)b;
} */
};
int main()
{
base b;
int a = 10;
b = a;
system("PAUSE");
return 0;
}
Output :
Could anyone please explain me the output ?
I expected just a call to
Default constructor.
Parameterized constructor.
I am unable to understand why I get a call to assignment operator and copy constructor other object being "int" type. If I uncomment "Asgn 2' I get a call to it rather that Asgn 1 which is understandable.
If I am getting a call to copy constructor (which always take object reference as its parameter), is it because compiler casts int to base type?
The output
default
base::int
base::assignment - base
base::cc
Comes about as follows:
base b;
Here create a b - This will use the default constructor
int a = 10;
b = a;
We have an assignment - the only one available takes a value of type base - so the compiler scratches its head and say "ah-ha" got a version of a constructor that can create an object of type base from an int. We can use that.
So you get the output
cout<<" base::int "<<endl;
Now the compiler can use the assignment operator. The parameter is an object of type base but as it is temporary this does not need to be called (see http://en.cppreference.com/w/cpp/language/copy_elision), The assignment operator then outputs
cout<<" base::assignment - base"<<endl;
But the assignment returns the value not as a reference - so it need to copy this return value into b - thus calling the copy constructor. Hence
cout<<" base::cc "<<endl;
First of all, base(int a) is a converting constructor as
it takes one argument
it doesn't use the explicit keyword
A converting constructor can be used for implicit conversions:
void foo(base b);
void bar() {
foo(3);
}
Here the int argument will be implicitly converted to base type with the converting constructor.
Because by value arguments (arguments passed by reference) are copied, the copy constructor is officially called; but here, the source of the copy is a temporary object, the implicitly created object using the int constructor. So the compiler is allowed to fuse the temporary and the parameter, directly constructing the target object. This optimisation is optional, and the compiler must still verify that the copy constructor could be called: that it is declared and accessible here (public).
Because the optimisation is very simple, almost all (or all?) compilers do it; many compilers do it at even the less aggressive optimisation levels (where most optimisations are disabled).
You declare the assignment operator as taking by a parameter by value and returning a copy (not a reference), which is quite rare (but not illegal):
/*Asgn 1*/ base operator=(base b){
cout<<" base::assignment - base"<<endl;
return b;
}
This means that the copy constructor is needed to pass an argument to the assignment operator, and also for return instruction.
Please note that the fact it is an operator is irrelevant, you could have called it assign:
/*Asgn 1*/ base assign(base b){
cout<<" base::assignment - base"<<endl;
return b;
}
and call it normally:
base a,b;
a.assign(b);
b.assign(base());
b.assign(base(2));
b.assign(3);
a.assign(b) will call the copy constructor to create the parameter of assign.
base() creates a temporary object using the default constructor, and base(2) creates one using the int constructor (when you explicitly create a temporary, it does not matter whether the constructor is a converting constructor). Then you can assign on the created temporary. The copy construction is avoided by the compiler by constructing directly the parameter.
In b.assign(3), the creation of the temporary is implicit, and the fact the constructor is a converting constructor is relevant.
The return statement creates another copy; the usual idiom for operator= is:
type& type::operator= (const type &source) {
copy stuff
return *this;
}
A reference is bound to the target object, and no redundant copying occurs.

C++ operator overloading

Why does the below C++ program output "ACCA"? Why is operator int() called twice?
#include "stdafx.h"
#include <iostream>
using namespace std;
class Base {
public:
Base(int m_var=1):i(m_var){
cout<<"A";
}
Base(Base& Base){
cout<<"B";
i=Base.i;
}
operator int() {
cout<<"C";
return i;
}
private:
int i;
};
int main()
{
Base obj;
obj = obj+obj;
return 0;
}
First, this line:
Base obj;
Default-constructs object obj by picking the constructor that accepts an integer, with default value 1. This is responsible for the first A being printed to the standard output.
Then, this expression:
obj + obj
Requires picking a viable overload of operator +. In this case, since obj has a user-defined conversion to int, the built-in operator + is picked, and both arguments are converted to int. This is responsible for the two Cs being printed to the standard output.
Then, the assignment to obj in:
obj = obj + obj
Needs to invoke the implicitly generated operator = for Base. The implicitly generated operator = has signature:
Base& operator = (Base const&);
This means that the expression on the right side of the equal sign, which is of type int, must be converted into a temporary Base object from which obj is assigned (the reference parameter of the implicitly-generated operator = is bound to this temporary).
But the creation of this temporary from an int in turn requires invoking the converting construction of Base that accepts an int again, which is responsible for the second A being printed to the standard output.
operator int() is called twice because you haven't overloaded operator+. The compiler doesn't know how to add a Base to a Base, so they are converted to int (since you taught it how to do that), which it does know how to do. The following code prints ADA:
#include <iostream>
using namespace std;
class Base {
public:
Base(int m_var=1):i(m_var){
cout<<"A";
}
Base(Base& Base){
cout<<"B";
i=Base.i;
}
operator int() {
cout<<"C";
return i;
}
int operator+(Base& Base)
{
cout<<"D";
return i+Base.i;
}
private:
int i;
};
int main()
{
Base obj;
obj = obj+obj;
return 0;
}
When you construct the object, you get the first "A":
Base obj;
When you specify to add obj+obj, the compiler needs to figure out a way to use + on obj. Since you didn't override an operator+ for Base, the conversion to int() gets called for each side of the equation:
obj+obj
This prints "CC".
Then, you assign to obj, which is of type Base, so the constructor which can accept an int (i + i from the int() operator) is run, which prints "A":
obj = obj+obj; // Assignment prints "A"
obj = obj+obj;
^^^--------obj converted to int here
^^^----obj converted to int here
^^^^^------------Base(int) ctor and default operator= called here
Overloading cast operators is not generally a good idea unless you understand the costs and know for a fact that the benefits in your specific case outweigh them.
how does below C++ program computes to "ACCA" ?
The first letter shown is 'A'. This output is related to this line:
Base obj;
... in which you are creating a new instance of Base.
The next line is a bit complicated:
obj = obj+obj;
Normally, this is translated to obj.operator+( obj ), but you don't have operator + overloaded in class Base, so this translation is not valid. The remaining possibility is that operator + is actually the numeric add operator.
And yes, this is possible, since you have provided a cast to int. So it is possible to convert each term of the equation in an int... and therefore operator int is called twice. The actual number of times operator int is called depends on the optimizations activated. For example, the compiler could realise that both terms are the same, and then create a new temporary once the operator int has been called the first time. In that case, you would see CA instead of CC.
Finally, the assignment expression obj.operator=( temp ) is executed. And here the keyword is temp. In order for the default operator= to work, since it is not overloaded, you have to have a Base object at the right. It is actually possible to have it, since Base uses an int to build new instances. Okay, so the result of obj + obj was an int (say it is called 'x') number, and the compiler creates a temporary object of class Base which is constructed with number x, as the following line was executed:
Base temp( x );
That's the way the final letter seen is an 'A'. Again, many compilers can avoid the building of temporaries on some cases, so it is possible not to see an 'A' at the end.
Note that this line:
obj = obj + obj
Was thus decomposed in:
int x = ( (int) obj ) + ( (int) obj );
Base temp( x );
obj = temp;
The final instruction has the result of as if the memory in which obj sits will be occupied with the contents of temp (that's the role of the default copy constructor, which executes operator= for each member of the class, see again the 'rule of three').
Operator overloading involves a lot of issues that maybe are not foreseen if you don't have a more or less deep knowledge of the language, as you can see. Take also into account that languages like Java totally prevent its use, while C# permits it from a controlled perspective.
You refer to obj twice in the expression obj+obj and each such reference has to be converted to an integer.
It's not impossible (although it is a horrible idea) that such a conversion could be "stateful" - that is, it could by design return a different value each time it is called. After all, the value represented by obj may change (it could be a counter or something like that). So the compiler has to evaluate it afresh for each reference.
It's call once per operand, it doesn't matter if it is the same instance.
obj = obj+obj;
It "casts" the first operand to an int, and then the second one.
You need to overload the operator + if you want to avoid this implicit cast.
It calls operator int() twice because it needs to convert both obj to int before it can add them.
The first A comes from
Base obj;
The two Cs come from converting obj in obj+obj to int as you didn't overload the operator +.
The last A comes from obj = conversion of the resulting int to obj.

Does dynamic_cast work inside overloaded operator delete?

I came across this:
struct Base {
void* operator new (size_t);
void operator delete (void*);
virtual ~Base () {} // <--- polymorphic
};
struct Derived : Base {};
void Base::operator delete (void *p)
{
Base *pB = static_cast<Base*>(p);
if(dynamic_cast<Derived*>(pB) != 0)
{ /* ... NOT reaching here ? ... */ }
free(p);
}
Now if we do,
Base *p = new Derived;
delete p;
Surprisingly, the condition inside the Base::delete is not satisfied
Am I doing anything wrong ? Or casting from void* looses the information of Derived* ?
Function operator delete is a raw-memory deallocation function. It is invoked when the actual object (that used to reside in that memory) has already been destructed. I.e. by the time you get into operator delete you object has already been wiped out. The memory the pointer points to is essentially "raw", it no longer contains an object. Trying to use any polymorphic functionality on this raw memory is useless - it will not work.
In more formal terms, according to the language standard the lifetime of an object with non-trivial destructor ends once its destructor starts. In your case all destructors have already done their work. The lifetime of the object is already over, while dynamic_cast requires a "live" object.
P.S. Formally, it is permissible to use dynamic_cast in a destructor as long as some conditions are met (see 12.7/5), but when all destructors are finished (as in your case), dynamic_cast is no longer usable.
Once your operator delete overload gets the pointer, the pointed-to object has been destroyed (the ~Derived() destructor has already been called).
You can't treat it like a Base or Derived object at all anymore after it is destroyed because it isn't a Base or Derived object anymore.
As already mentioned by the other two answers, the type of an object changes as the destructors are being executed. Once a destructor completes, the object of that type does no longer exist, and only it's base subobjects exists (until their destructors complete).
The reason for this answer is proposing an interesting experiment, what will the output of this code be? (Oh, well, all three answers already told you, but the experiment is interesting in itself):
#include <iostream>
struct base {
static void print_type( base const & b ) { // [1]
std::cout << b.type() << std::endl;
}
virtual std::string type() const { // [2]
return "base";
}
virtual ~base() { print_type( *this ); }
base() { print_type( *this ); }
};
struct derived : base {
std::string type() const {
return "derived";
}
~derived() { print_type( *this ); }
derived() { print_type( *this ); }
};
struct most_derived : derived {
std::string type() const {
return "most_derived";
}
~most_derived() { print_type( *this ); }
most_derived() { print_type( *this ); }
};
int main() {
most_derived md;
base::print_type( md );
}
Notes:
For extra fun, calls to print_type are also added in the constructor. The function serves as verification of the dynamic type of the object at that particular point in time. The function print_type (that could be a freestanding function, and implemented in a different translation unit --as to avoid the compiler from seeing inside it). While compiling the function, the compiler cannot know whether it is called from inside a constructor, destructor, or outside of any of them, so the generated code must use the dynamic dispatch mechanism, and will be dispatched to the final overrider at each point in time.
As to the validity of the code is guaranteed by ยง12.7/2:
To explicitly or implicitly convert a pointer (an lvalue) referring to an object of class X to a pointer (reference) to a direct or indirect base class B of X, the construction of X and the construction of all of its direct or indirect bases that directly or indirectly derive from B shall have started and the destruction of these classes shall not have completed, otherwise the conversion results in undefined behavior. To form a pointer to (or access the value of) a direct nonstatic member of an object obj, the construction of obj shall have started and its destruction shall not have completed, otherwise the computation of the pointer value (or accessing the member value) results in undefined behavior.
Conversions to base& on the call to print_type are valid as they are performed after the construction of each object has started, and before the destruction of each object has completed (each refers to each one of the subobjects of most_derived in the program).

c++ inheritance question

I have a question about this:
class A
{
int a;
int* pa;
public:
A(int i):a(i) , pa(new int(a))
{
cout<<"A ctor"<<a<<endl;
}
~A()
{
delete pa;
cout<<"dtor\n";
}
int * &get()
{
return pa;
}
};
class B : public A
{
int b;
public:
B (A obj): A(obj) , b(0)
{
cout<<"B ctor\n";
}
~B()
{
cout<<"B dtor\n";
}
};
int main()
{
int i = 23 ;
A* p = new B(i);
}
Can tell me why the last line in main compiles? I pass an int into B's constructor which expects an A object instead. I believe that the int is translated to an A in B's constructor, but why?
Thanks in advance.
Avri.
Since you have not declared A constructor as explicit compiler is creating an anomymous instance of A using i and using it to initialize B instance. If you don't want the compiler to do these implicit conversions declare your costructor as explicit. Then you will get a compiler error.
Because A has a single parameter constructor which takes an int and isn't marked explicit you can implicitly convert an int to an A.
When you do new B(i), because the only viable constructor for B takes an A, an attempt is made to convert i to an A and construct the new B from that. This conversion is done by creating a temporary A using the constructor that takes an int.
When the B object is constructed, the base class A is copy constructed from the temporary A which means copying the member variables a and pa from the temporary A.
Strictly, because the constructor takes an A object by value, the temporary is, conceptually, copied again. The compiler may, however, eliminate the temporary by constructing the constructor parameter for B directly from i so the effect may well look like just a single copy.
This will cause a serious error because when the temporary A is destroyed, delete pa will cause the dynamically allocated int to be destroyed but the base class A of the newly allocated B object will still have a copy of this pointer which now no longer points at an invalid object. If the compiler doesn't eliminate one of the copies, a "double free" will happen immediately.
The key aspect of A is that it has a user-defined destructor that performs a resource action (deallocation). This is a strong warning that A needs a user-defined copy constructor and copy assignment operator because compiler generated version are likely not to work consistently with the design of A.
This is known as the "rule of three" which says that if you need a user-defined version of one of the destructor, copy constructor or copy assignment operator then you are likely to need user-defined versions of all of them.
Were you to attempt to free the dynamically allocated B object in your example, it would likely cause a "double free" error. In addition, A's destructor would need to be marked as virtual for a delete through a pointer to A to work correctly.
Since there is a conversion from int to A, implicitly your code is translated into
A* p = new B(A(i));