Friday, 29 November 2013

Some C++ concepts from daily programming life



Standardization: Available and released version of C++

YearC++ StandardInformal name
1998ISO/IEC 14882:1998C++98
2003ISO/IEC 14882:2003C++03
2007ISO/IEC TR 19768:2007C++TR1
2011ISO/IEC 14882:2011C++11


Managed and Unmanaged objects in c++


The concept of Managed or Unmanaged objects is not typically C++. It is related to Microsoft .Net technology. Basically somewhere related to memory management and garbage collection.
If you are using normal or native C++ language, your application itself is responsible for deleting all the memory it has allocated dynamically. Due to which the developer has to be very careful about maintaining the object lifetime. If memory is sooner than its use is over, the application may crash. If memory is not deleted at all, the application results in memory leak.
Environments like Java and .Net solve this problem by using garbage collectors. The developer do not have to delete objects and care about the lifetime of the objects any more, the garbage collector will do this for him.
In the 'native' .Net languages (like C#), the whole language works with the garbage collector concept. To make the transition from normal, plain C++ applications to .Net easier, Microsoft added some extensions to its C++ compiler, so that C++ developers could already benefit from the advantages of .Net.
Whenever you use normal, plain C++, Microsoft talks about unmanaged, or native C++. If you use the .Net extensions in C++, Microsoft talks about managed C++.

 If your application contains both, you have a mixed-mode application.


Strict weak ordering

A Binary predicate* that allows you for more general interpretation of equality.
That typically means you do not actually follow the actual comparison of value by value but does a more subjective comparison. One way to achieve this by overloading "operator<()" and then writing our own weak or subjective comparison logic built.

This concept is also used by container class to sort the keys in its hash or containers.
*Predicate:- A simple function that returns a boolean value, could be result of some calculation.
$Note- more to be coming soon on this topic.



To suppress any warning in C++ compilers



#pragma warning( disable : 4786)
#pragma warning( disable : 4503)
#pragma warning( disable : 4290)
#pragma warning( disable : 4996)

Note:- Use the warning error no.



Why Sizeof operator cannot be overloaded


Sizeof cannot be overloaded because built-in operations, such as incrementing a pointer into an array implicitly depends on it. Consider:
 X a[10];
 X* p = &a[3];
 X* q = &a[3];
 p++; // p points to a[4]
// thus the integer value of p must be
// sizeof(X) larger than the integer value of q

Thus, sizeof(X) could not be given a new and different meaning by the programmer without violating basic language rules.
Note:- note the addition of size to get the new pointer.

Courtesy stroustrup.com

In C++ we cannot define our own operators

It may lead to subtle bugs because of having difference in opinion about the behaviour of operator while looking at it.

For e.g.
3 ** 2 means 3*2*2 for me but to someone else it make more sense as 3^(2*2). 
So to avoid any such confusion we cannot define our own operators.

Difference between Scope, Lifetime and Visibility of objects/variables

Lifetime is the total time between an object's creation and destruction. 
Scope is those sections of the code where an identifier (whether it represents a variable, a function or anything else) is legally accessible. 
Visibility is those sections where the identifier is in scope and has not been masked by the reuse of the identifier in a more local scope. 
Lifetime >= Scope >= Visibility. 

A global variable might have a lifetime that equals the entire execution of the program and would always be in scope, but would not be visible in a function where its name was reused for a local variable



Significance of arrow operator?



In C, a->b is precisely equivalent to (*a).b. The "arrow" notation was introduced as a convenience; accessing a member of a struct via a pointer was fairly common and the arrow notation is easier to write/type, and generally considered more readable as well.
C++ adds another wrinkle as well though: operator-> can be overloaded for a struct/class. Although fairly unusual otherwise, doing so is common (nearly required) for smart pointer classes.
That's not really unusual in itself: C++ allows the vast majority of operators to be overloaded (although some almost never should be, such as operator&&operator|| and operator,).
What is unusual is how an overloaded operator-> is interpreted. First, although a->b looks like ->is a binary operator, when you overload it in C++, it's treated as a unary operator, so the correct signature is T::operator(), not T::operator(U) or something on that order.
The result is interpreted somewhat unusually as well. Assuming foo is an object of some type that overloads operator->foo->bar is interpreted as meaning (f.operator->())->bar. That, in turn, restricts the return type of an overloaded operator->. Specifically, it must return either an instance of another class that also overloads operator-> (or a reference to such an object) or else it must return a pointer.
In the former case, a simple-looking foo->bar could actually mean "chasing" through an entire (arbitrarily long) chain of instances of objects, each of which overloads operator->, until one is finally reached that can refer to a member named bar. For an (admittedly extreme) example, consider this:
#include <iostream>

class int_proxy {
    int val;
public:
    int_proxy(): val(0) {}
    int_proxy &operator=(int n) { 
        std::cout<<"int_proxy::operator= called\n";
        val=n; 
        return *this; 
    }
};

struct fubar {
    int_proxy bar;
} instance;

struct h {
    fubar *operator->() {
        std::cout<<"used h::operator->\n";
        return &instance;
    }
};

struct g {
    h operator->() {
        std::cout<<"used g::operator->\n";
        return h();   
    }
};

struct f {
    g operator->() { 
        std::cout<<"Used f::operator->\n";
        return g();
    }
};

int main() {
    f foo;

    foo->bar=1;
}
Even though foo->bar=1; looks like a simple assignment to a member via a pointer, this program actually produces the following output:
Used f::operator->
used g::operator->
used h::operator->
int_proxy::operator= called
Clearly, in this case foo->bar is not (even close to) equivalent to a simple (*foo).bar. As is obvious from the output, the compiler generates "hidden" code to walk through the whole series of overloaded -> operators in various classes to get from foo to (a pointer to) something that has a member named bar (which in this case is also a type that overloads operator=, so we can see output from the assignment as well).

{http://stackoverflow.com/questions/13023320/the-arrow-member-operator-in-c}


Pointers Vs Reference.  When to use and why?

Note:- Not covering the definitions

1) References can never be null. 
 
  string& str1;             // Error! References must  be initialized  
  string str("xyzzy");  
  string& str1 = str;         // okay, str1 refers to str  

There is no such restriction in pointer. SO whenever we use pointer we tend to check for the possibility of its being null and then we use it. We dont have to bother about this when using references. This way references are safer to use.

2) Pointer may be reassigned to point out to some other objects as well. this is not the case with reference, it is assigned to the object with which it is initialized.

Hence, use pointers when there is possibility of the pointer referring to different things.
Use reference when you wanted to refer to only one object.

Note:- When ever you are implementing certain operators always use references.


No comments:

Post a Comment