Friday, 10 April 2020
Thursday, 9 April 2020
Advanced C++
Constant
#include<stdio.h>
#include<iostream>
using namespace std;
#include<string>
#include<string.h>
class ManageNumber
{
int num;
public:
ManageNumber(int value)
{
}
int get()
{
return num;
}
};
void Print(const ManageNumber& n)
{
cout<<n.get();
}
int main()
{
ManageNumber num(200);
Print(num);
}
Will this code compile ?
n.get();
No : The object has type qualifier which is not compatible with member function
Solution : Make get function as constant.
********************
char* ptr="hello";
*ptr='a';
Will it work ?
No , It will crash. Access Violation writing location
********************
Any thing having internal linkage can be defined in header file.
Constant is having internal linkage .
Important points for const
Use wherever a constant value is required
Can be defined in a header file
If a external linkage is required , use extern while defining.
Use to specify read only methods (object querying methods like getters)
Qualify pass by reference values so that object is not modified.
Qualify references or pointers with const when returning from a function of a class.
Avoid using const_cast to remove const behaviour
Reference Type:
A reference is an alias or an alternative name of an object.
It allows for indirect manipulation of the object similar to that of a pointer but without requiring pointer syntax.
The most common use of references in C++ is for passing objects as arguments to functions and return arguments.
Reference always points to lvalue .Because it is referring to data which is having some address
int data=5;
int & ref =data
ref is reference and data is referent. Both point to same location.
ref=x;
Assign the value of x to data;
int* ptr =&ref;
//Not a pointer to reference its a pointer to referent.
int * & refptr =ptr
//reference to a pointer.
int data=5;
int x=1;
int &ref=data;
cout<<endl<<data<<endl; //5
ref=x;
cout<<"\n"<<data<<"\n"; //1
Suppose if you want to pass an object to function by value copy of object is created
stack will have to allocate memory for objects and also copy is created through copy constructor .
So to avoid this we will use reference . Using reference we can do indirect manipulation of object .
Pass by value problem
By default objects are pass by value -Copy is created and copy constructor is called .
Another problem is a function accepting a base object by value will work incorrectly when a derived object is passed to it .
-The compiler will slice the derived object to match the size of the base object.
#include<stdio.h>
#include<iostream>
using namespace std;
class Line
{
int x1,x2,x3,x4;
public:
virtual void draw() const
{
cout<<"LINE";
}
};
class DashedLine:public Line
{
int dash_type;
public:
void draw()const
{
cout<<"DashLine";
}
};
void paint(const Line& l)
{
l.draw();
}
int main(void)
{
DashedLine dl;
paint(dl); //Dashed Line
return 0;
}
#include<stdio.h>
#include<iostream>
using namespace std;
class Line
{
int x1,x2,x3,x4;
public:
virtual void draw() const
{
cout<<"LINE";
}
};
class DashedLine:public Line
{
int dash_type;
public:
void draw()const
{
cout<<"DashLine";
}
};
void paint(Line l)
{
l.draw();
}
int main(void)
{
DashedLine dl;
paint(dl); //Line
return 0;
}
Line is having space for 16 bytes and Dash line requires space for 20 bytes.
This will cause compiler to slice of extra 4 bytes. This is also called object slicing.
When you use a normal object l to invoke a virtual function virtual mechanism will not work .
Pass by Reference
The objects should be passed by reference to avoid memory allocation
unnecessary copies
incorrect behaviour due to slicing.
It would be however more appropriate to qualify pass by reference objects with const
- the function can modify original value .
But for built in types , STL iterators & function objects , pass by value is inexpensive .
const int & ref3=5;
you can create a constant reference to a literal.
int array[5]={3,1,8,34,9}
int (&refarray)[5] = array
Reference to an arraay of 5 integers.
int &Add (int x, int y)
{
int sum=x+y;
return sum;
}
//cannot return reference or address of a local variable.
Reference vs Pointer
#include<stdio.h>
#include<iostream>
#include<string>
using namespace std;
void print(string * pstr) //For pointer we need to do null check
{
cout << *pstr;
}
void print(string & pstr) //Null check is not required
{
cout << pstr;
}
int main(void)
{
string name("Umar");
string *pstr= &name;
print(pstr);
string &str= name;
print(str);
}
Which function is safer to call
For pointer we need to do null check
Reference is bound to lvalue there is always some value .
Reference can never be null.
pointer will better when a pointer has to store different address.
Reference once initialized cannot be changed.
Returning by Reference
It may not be possible to return a value by reference all the times (it may be local)
However for non local data take advantage of reference mechanism.
Several overloaded operators can return by reference eg [].*.+=,==,etc.
For some operators it may not be possible ,because they require a temporary object ex +,-,postfix++ and -- etc.
Reference type Rules
Reference have to be initialized while being declared.
A reference is bound to its referent and the referent cannot be changed later.
A reference can be bound only to lvalue
A constant reference can bound to r value
A reference cannot be null.
You cannot get address of a reference.
References can be declared as extern and then defined elsewhere
you cannot have an array of references.
you can have reference to a pointer or pointer to a reference .
Advice
Pass objects by constant reference
consider return value optimization when returning large objects (or C++11 move semantics)
Don't use reference arguments as return type
-use pointer instead.
int test(int* p, int* q, int*r) //Pointer is preferred
{}
int main(void)
{
int i,j,k;
test(&i,&j,&k);
return 0;
}
Primitive types should be passed by value.
Inline Function
Very small function can be declared inline
This keyword is a hint to the compiler that the function call should be replaced with the definition
There could be several reason for doing so.
-You don't want the overhead of a function call
If you use macros ,they are simple test substitution mechanism unknown to the compiler .
You don't get function semantics (debugging,type checking etc.)
If you replace the call of the function with the actual code manually , what if you need to change the
function code later.
-Its easier to interpret a function call rather than to read the code of the function
Functions defined within the class body are automatically inlined.
int square(int x)
{
return x*x;
}
int main(void)
{
int i=5;
int result=square(i); //Arguments has to put on stack then function call is to be made return address has to be saved then jump to the function Memory has to be allocated to local variable
return 0;
}
inline can be applied only on function definition
Inline function is having external linkage
Multiple definition of inline function is discarded by compiler only one will be considered.
Inline functions
Note that inline is only a request to the compiler.
The compiler may choose to ignore it because the function may not be a good candidate for inlining
Reason could be
-its a recursive function and depth could not be determined at compile time
-the function is called through a function pointer.
-the function has a variable argument list.
-the function is virtual , although direct calls to the function can be inlined
Inlining preserves the semantics of a function it will still have address and can contain static variables
Inline very small function
setters and getters in a class can be inlined and can be defined in the header file itself.
-excepts when they contain sensitive code.
Define inline functions inside a header file so that they are accessible to all the files that call them
Avoid excessive inlining especially for large functions (increase size of executables)
Avoid putting static data in inline functions
Inlining may not always increase run time performance
-profile your code to see if inlining is really helpful
-modern compiles may automatically inline some functions.
Ex : In C++ all time related functions are in chrono namespace .
Argument dependent lookup or koenig lookup
Suppose Math is namespace
Math:: Complex c1(10,20);
print(c1);
Suppose print is also in math namesapce but not required to call using manespace as argument (c1) is created using namespace .It is called argument dependent lookup
Alias for namespace
namespace math =Mathematics
Yes it will work.

#include<stdio.h>
#include<iostream>
using namespace std;
#include<string>
#include<string.h>
class ManageNumber
{
int num;
public:
ManageNumber(int value)
{
}
int get()
{
return num;
}
};
void Print(const ManageNumber& n)
{
cout<<n.get();
}
int main()
{
ManageNumber num(200);
Print(num);
}
Will this code compile ?
n.get();
No : The object has type qualifier which is not compatible with member function
Solution : Make get function as constant.
********************
char* ptr="hello";
*ptr='a';
Will it work ?
No , It will crash. Access Violation writing location
********************
Any thing having internal linkage can be defined in header file.
Constant is having internal linkage .
Important points for const
Use wherever a constant value is required
Can be defined in a header file
If a external linkage is required , use extern while defining.
Use to specify read only methods (object querying methods like getters)
Qualify pass by reference values so that object is not modified.
Qualify references or pointers with const when returning from a function of a class.
Avoid using const_cast to remove const behaviour
Reference Type:
A reference is an alias or an alternative name of an object.
It allows for indirect manipulation of the object similar to that of a pointer but without requiring pointer syntax.
The most common use of references in C++ is for passing objects as arguments to functions and return arguments.
Reference always points to lvalue .Because it is referring to data which is having some address
int data=5;
int & ref =data
ref is reference and data is referent. Both point to same location.
ref=x;
Assign the value of x to data;
int* ptr =&ref;
//Not a pointer to reference its a pointer to referent.
int * & refptr =ptr
//reference to a pointer.
int data=5;
int x=1;
int &ref=data;
cout<<endl<<data<<endl; //5
ref=x;
cout<<"\n"<<data<<"\n"; //1
Suppose if you want to pass an object to function by value copy of object is created
stack will have to allocate memory for objects and also copy is created through copy constructor .
So to avoid this we will use reference . Using reference we can do indirect manipulation of object .
Pass by value problem
By default objects are pass by value -Copy is created and copy constructor is called .
Another problem is a function accepting a base object by value will work incorrectly when a derived object is passed to it .
-The compiler will slice the derived object to match the size of the base object.
#include<stdio.h>
#include<iostream>
using namespace std;
class Line
{
int x1,x2,x3,x4;
public:
virtual void draw() const
{
cout<<"LINE";
}
};
class DashedLine:public Line
{
int dash_type;
public:
void draw()const
{
cout<<"DashLine";
}
};
void paint(const Line& l)
{
l.draw();
}
int main(void)
{
DashedLine dl;
paint(dl); //Dashed Line
return 0;
}
#include<stdio.h>
#include<iostream>
using namespace std;
class Line
{
int x1,x2,x3,x4;
public:
virtual void draw() const
{
cout<<"LINE";
}
};
class DashedLine:public Line
{
int dash_type;
public:
void draw()const
{
cout<<"DashLine";
}
};
void paint(Line l)
{
l.draw();
}
int main(void)
{
DashedLine dl;
paint(dl); //Line
return 0;
}
Line is having space for 16 bytes and Dash line requires space for 20 bytes.
This will cause compiler to slice of extra 4 bytes. This is also called object slicing.
When you use a normal object l to invoke a virtual function virtual mechanism will not work .
Pass by Reference
The objects should be passed by reference to avoid memory allocation
unnecessary copies
incorrect behaviour due to slicing.
It would be however more appropriate to qualify pass by reference objects with const
- the function can modify original value .
But for built in types , STL iterators & function objects , pass by value is inexpensive .
const int & ref3=5;
you can create a constant reference to a literal.
int array[5]={3,1,8,34,9}
int (&refarray)[5] = array
Reference to an arraay of 5 integers.
int &Add (int x, int y)
{
int sum=x+y;
return sum;
}
//cannot return reference or address of a local variable.
Reference vs Pointer
#include<stdio.h>
#include<iostream>
#include<string>
using namespace std;
void print(string * pstr) //For pointer we need to do null check
{
cout << *pstr;
}
void print(string & pstr) //Null check is not required
{
cout << pstr;
}
int main(void)
{
string name("Umar");
string *pstr= &name;
print(pstr);
string &str= name;
print(str);
}
Which function is safer to call
For pointer we need to do null check
Reference is bound to lvalue there is always some value .
Reference can never be null.
pointer will better when a pointer has to store different address.
Reference once initialized cannot be changed.
Returning by Reference
It may not be possible to return a value by reference all the times (it may be local)
However for non local data take advantage of reference mechanism.
Several overloaded operators can return by reference eg [].*.+=,==,etc.
For some operators it may not be possible ,because they require a temporary object ex +,-,postfix++ and -- etc.
Reference type Rules
Reference have to be initialized while being declared.
A reference is bound to its referent and the referent cannot be changed later.
A reference can be bound only to lvalue
A constant reference can bound to r value
A reference cannot be null.
You cannot get address of a reference.
References can be declared as extern and then defined elsewhere
you cannot have an array of references.
you can have reference to a pointer or pointer to a reference .
Advice
Pass objects by constant reference
consider return value optimization when returning large objects (or C++11 move semantics)
Don't use reference arguments as return type
-use pointer instead.
int test(int* p, int* q, int*r) //Pointer is preferred
{}
int main(void)
{
int i,j,k;
test(&i,&j,&k);
return 0;
}
Primitive types should be passed by value.
Inline Function
Very small function can be declared inline
This keyword is a hint to the compiler that the function call should be replaced with the definition
There could be several reason for doing so.
-You don't want the overhead of a function call
If you use macros ,they are simple test substitution mechanism unknown to the compiler .
You don't get function semantics (debugging,type checking etc.)
If you replace the call of the function with the actual code manually , what if you need to change the
function code later.
-Its easier to interpret a function call rather than to read the code of the function
Functions defined within the class body are automatically inlined.
int square(int x)
{
return x*x;
}
int main(void)
{
int i=5;
int result=square(i); //Arguments has to put on stack then function call is to be made return address has to be saved then jump to the function Memory has to be allocated to local variable
return 0;
}
inline can be applied only on function definition
Inline function is having external linkage
Multiple definition of inline function is discarded by compiler only one will be considered.
Inline functions
Note that inline is only a request to the compiler.
The compiler may choose to ignore it because the function may not be a good candidate for inlining
Reason could be
-its a recursive function and depth could not be determined at compile time
-the function is called through a function pointer.
-the function has a variable argument list.
-the function is virtual , although direct calls to the function can be inlined
Inlining preserves the semantics of a function it will still have address and can contain static variables
Inline very small function
setters and getters in a class can be inlined and can be defined in the header file itself.
-excepts when they contain sensitive code.
Define inline functions inside a header file so that they are accessible to all the files that call them
Avoid excessive inlining especially for large functions (increase size of executables)
Avoid putting static data in inline functions
Inlining may not always increase run time performance
-profile your code to see if inlining is really helpful
-modern compiles may automatically inline some functions.
Ex : In C++ all time related functions are in chrono namespace .
Argument dependent lookup or koenig lookup
Suppose Math is namespace
Math:: Complex c1(10,20);
print(c1);
Suppose print is also in math namesapce but not required to call using manespace as argument (c1) is created using namespace .It is called argument dependent lookup
Alias for namespace
namespace math =Mathematics
Yes it will work.
Subscribe to:
Posts (Atom)