C++ quick facts

Compiler settings
  1. Use –pedantic-errors compiler flag. It will guarentee that code is compiled according to used c++ standard. If this flas is not used, sometimes, compiler extensions allow some specific code which is not compatible with standard to compile without an error.

    For example – If flag is not used then, g++ compiler will give warnings instead of error for some type conversions which are not correct according to c++ standard.

    Please see https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Extensions.html for extension details.
Pointers
  1. Pointers to functions and pointers to members cannot be assigned to the void pointers.
  2. In c++, it is good practice to initialize pointers with “nullptr”  instead of 0.

Arrays

  1. Giving a surplus size when initializing an array will result in an error. Below statement will result in an error.
    char v3[2] = { ‘a’, ‘b’, 0 };

  2. If the initializer supplies too few elements for an array, 0 is used for the rest.
    int v5[8] = { 1, 2, 3, 4 };     =>     int v5[] = { 1, 2, 3, 4 , 0, 0, 0, 0 };

  3. You can not initialize the array by using another array. You can not assign one array to another array.

    int x[10] = {0};    //Array initilized with 0s
    int y[10] = {0};    //Array initialized with 0s
    int z[10] = x;    //error
    y = x;    //error

  4. To delete an array, a bracket is needed but for normal variable it is not needed. 
     
    delete [] a;
    delete a;

String literals

  1. If you do not want to consider escape characters in the string, you can use R prefix in front of string in following form –
    const char * p = R”(Raw string)”;
    const char * p = R”pattern(Raw string)pattern”;

    Notice that we can use any pattern of characters in between ” and (Same pattern should be repeated between ) and “
    I don’t know what would be the use of such pattern except beautification of the code. 

  2. String can be represented by 3 UTF formats –
    const char * p = u8″string”;     //UTF-8 string
    const char * p = u”string”;     //UTF-16 string
    const char * p = U”string”;     //UTF-32 string
     
  3.  For a character variable, if a character with escape character is assigned, it digits are considered as octal.
    e.g.
    char i = ‘\45’;   
    The value would be 45 (octal) = 37 (decimal) = ‘%’
    What could be the reason of considering it as octal??

Array and pointers

  1. If you add the ‘n’ number to the array name, it will point to the ‘n’th element.
    int a[10];
    int *b = a + 2     //No error, No warning, and value of b will be &a[2]
    int *b = a – 2     //No error, No warning, and value of b will be undefined.


  2. Addition/multiplication/division of 2 pointers is not allowed. Subtraction of 2 pointer is allowed.
    Adding and subtracting an integer is allowed. 

     

  3. Substraction of 2 pointers is allowed and it gives the number of data items between the pointers.
    That’s why substraction of addresses of “same array” element is okey as long as it is in the range of array size. But the result of substraction of “different array” element would be undefined.
    int v1[10];
    int v2[10];
    int i1 = &v1[5] – &v1[3];     //i1 = 2
    int i2 = &v1[5] – &v2[3];     //result undefined.


  4. If you substract the addresses of 2 “same array” elements, it will not give you the real difference between actual address.
    As we can see in above example, value of i1 is 2, even if the real difference between the 2 addresses is 8.


  5. For-range can be used for array whose size is defined. For-range gives compilation error if used with pointers.
    void fn(int a1[])
    {
        int a2[10];
        for (int x : a1)    //Compilation error
            use(x);
        for (int x : a2)    //No error , No warning. 
            use(x);
    }


  6. You will need to pass an integer pointer if you are catching an integer pointer. 
    See the bold statement in below example.

    void print_mi5(int m[][5], int dim1);
    void print_m35(int m[3][5]);
    void print_mij(int* m, int dim1, int dim2);

    int test()
    {
        int v[3][5] =        {0,1,2,3,4}, {10,11,12,13,14}, {20,21,22,23,24}};

        print_m35(v);
        print_mi5(v,3);
        print_mij(v,3,5);    //Compilation error, because v is not an integer pointer. v[0] or &v[0][0] will work
    }

     

  7. Meaning of ‘const’ –

    char a;
    char ∗const ptr  = &a;       //value of ptr is constant. ptr could not be changed by using assignment.
    char const∗ ptr  = &a;       //Value pointed by pointer ptr is constant. value of ‘a’ could not be changed by using (*ptr)
    const char∗ ptr  = &a;       //same as above – Value pointed by pointer ptr is constant. value of ‘a’ could not be changed by using (*ptr)

References

  1. Like constants, references must be initialized. Uninitialized references will give compilation error.
  2. Lvalue refer to the object of the variable and Rvalue refers to the value of variable. For example – 
    int var = 10;
    Here, lvalue of var is the object named by var – which is int. And the rvalue of var is 10.

Cin

  1. String is terminated by whitespace – it could be a space, a tab or a newline. 
  2. Whitespaces are simply ignored by cin. 
    cin >> str_1;
    cin >> int_1;
    if we give input as “string     11” , string will be stored in str_1 and 11 will be stored in int_1. All the whitespacess will be ignored.
  3. You can use if(cin) to know the status of last cin opetation. if cin is 0, it means there was an error. 

Cout

  1. cerr is used for error messages.
  2. Manipulator – 
    int a = 10;
    cout << hex << a;
    An a will appear on the console. 
    A manipulator is a function which modifies the basefield property of the output stream.
  3. Manipulator – 
    the result will be printed on console each time the manipulator gets activated. 
    cout << byte << dec <<byte << dec << byte;

Operators

  1. Type of a variable determines what operations we can apply to it and what they mean.
    e.g. we can not apply operation % to double type variable.
  2. Use { .. } instead of = operator for initialization because it gives error on narrowing. Ex –
    char var1 =  1000;    //No error
    char var2 { 1000 } ;    //Error

Keywords

  1. constexpr is the new keyword added in c++11 It was not present in C and C++98.
  2. sizeof is not only a keyword but also an operator.
    e.g.
    Both statements are valid – 
    i = sizeof(var); 
    i = sizeof var;
    but i = sizeof char; //will give an error.

General

  1. A sequence of statements delimited by curly braces {… } is called a block or a compound
    statement. A block is a kind of statement.

Vectors

  1. Vector contains size in itself.
  2. push_back() is used to add an element to the vector.
  3. we can give vector as an argument to the sort() function. same vector will be modified and sorted.  
  4. Vector can be used for range for ex-
    vector<double> vec;
    double tmp;
    while(cin>>tmp) vec.push_back(tmp);
    for (double x : vec)
  5.  

Strings

  1. Comparison operators work as below – 

    int main ()
    {
    std::string foo = “alpha”;
    std::string bar = “beta”;

    if (foo==bar) std::cout << “foo and bar are equal\n”;
    if (foo!=bar) std::cout << “foo and bar are not equal\n”;
    if (foo< bar) std::cout << “foo is less than bar\n”;
    if (foo> bar) std::cout << “foo is greater than bar\n”;
    if (foo<=bar) std::cout << “foo is less than or equal to bar\n”;
    if (foo>=bar) std::cout << “foo is greater than or equal to bar\n”;

    return 0;
    }

Functions

  1. In C++, every function call must provide the expected number of arguments, of the right types, and in the right order.

Errors

  1. Narrowing errors can be caught by using the below format.
    int x1 = narrow_cast<int>(2.9); // throws
    int x2 = narrow_cast<int>(2.0); // OK
    char c1 = narrow_cast<char>(1066); // throws
    char c2 = narrow_cast<char>(85); // OK

Switch 

  • If you want to define and initialize variables within a switch statement, you must place them inside a block.

 

Declaration and Definition

  • In addition to the variable, constants, Functions and enums, we can define classes, namespaces and templates in c++.
  • Except for class members, the C++ definition requires declaration before use. 
  • String, vectors etc. are not primitive data types in c++ so their initial value is defined by constructors. 
  • The rule that “name must be declared before it is used” is relaxed withing limited scope of the class. e.g. we can use the variable in member function definition before declaring it as a char or float or as any datatype later in the class. 
  • If you put member definitions in class declaration, the member definitions will become inline. 

Scope

  • Type of scopes –
    A global scope: the area of text outside any other scope.
    A namespace scope: a named scope nested in the global scope or in another namespace.
    A class scope: the area of text within a class.
    A local scope: between { . . . } braces of a block or in a function argument list.
    A statement scope: e.g., in a for-statement.
  • A private static variable in the class can not be initialized in the class. It has to be done outside of the class. It must be initialized otherwise compiler will throw an error.
    e.g. int Class::static_var= 0;
    if you try to do that, the compiler will throw an error – “ISO C++ forbids in-class initialization of non-const static member” which is understandable. 
  • static components can be accessed by directly the class reference.
    e.g. Class::static_var= 0;
    e.g. Class::static_fun();
  • If there is an object inside an object, and the default constructure of child needs a parameter, then we can also initialize the child’s constructure while defining the parents constructure in below way.
    class Child{
    int value;
    public:
    Child(int value) {
    this -> value = value;
    }
    class Parent{
    Child Ch1, Ch2;
    public:
    Parent() : Ch2(2), Ch1(1)
    {
    //Ch1 will be created first, then Ch2
    }
    Moreover, in the above snippet, if there is a default constructure for Child without any parameter – then the compiler should throw an error because there would be an ambiguity to choose from parametered and parameterless constructure, right? – wrong, compiler will not find it ambiguous and it will chose the paramtered constructure. I don’t like cpp. 

Function call and Return

  • In the definition of the function, we can keep some arguments without their name. This is useful when we want to remove some argument that was used in the past. 
    e.g. void fun_1(int a, int b, int) 

Program Text

  • A single statement could be written on multiple lines, without need of inserting “\” character at the end.
    e.g.
    cout
    <<
    “your string.”
    ;
    Above statement will compile without errors.

Difference from C

  • “Default parameters” is not supported by C99 standard. 

Constructors

  • Derived constructors are defined as below. 
    AddingStack::AddingStack(void):stack(){
    sum=0;
    }
    why not like below?
    AddingStack::AddingStack(void){
    stack::stack()
    sum=0;
    }

Not understood

  • How this program compiles without error?

#include <iostream>

using namespace std;
class A{
public:
A(float v){};
};

int main()
{
A *a=new A(1.0), *b=new A(*a);
return 0;
}

const after the argument list

This feature is not available in C
int day() const {return d;}
Month month() const{return m;}
The object can not be modified in below declaration:
int Date::day() const
{
    ++d; //error
    return d;
}

 

Leave a Comment

Your email address will not be published. Required fields are marked *