Self-test 3:
Constructors & Destructors

  1. Which of the followings is/are automatically and unconditionally added to every class, if we do not write our own?

    1. Copy Constructor.
    2. Assignment Operator.
    3. A constructor without any parameter.
    4. A and B only.
    5. All of the above.
    Solution
    D is correct. In C++, if we do not write our own copy constructor and assignment operator for a class, the compiler automatically creates them. The default constructor will also be created by the compiler but only under the situation when no constructors of any kind are defined for a class.

  2. When a copy constructor may be called?

    1. When an object of the class is returned by value.
    2. When an object of the class is passed (to a function) by value as an argument.
    3. When an object is constructed based on another object of the same class
    4. All of the above.
    Solution
    D is correct. Conceptually a copy constructor may be called in following cases:
    • When an object of the class is returned by value.
    • When an object of the class is passed (to a function) by value as an argument.
    • When an object is constructed based on another object of the same class.
    • When compiler generates a temporary object.
    It is, however, not guaranteed that a copy constructor will be called in all these cases, because the C++ Standard allows the compiler to optimize the copy away in certain cases, one example being the return value optimization (sometimes referred to as RVO).

  3. Which, if any, of the following statements are not true? Why?

    1. A class must provide at least one constructor.
    2. A default constructor is a constructor with no formal parameters in its parameter list.
    3. If there are no meaningful default values for a class, the class should not provide a default constructor.
    4. We can have more than one constructor in a class, as long as each has a different list of arguments.
    Solution
    A, B and C are not true. A is not true; even if no constructor of any kinds are provided, the compiler still will give you a default constructor. B is not true (this is a tricky question); e.g., Word(int f = 0, char* s = nullptr) { frequency = f; str = s; } is still a default constructor though its parameter list consists of 2 variables because it may be called with no arguments due to the use of defaults values for both formal parameters. C is not true, constructor may assign default values to object, indicating that the object has invalid initial values.

  4. Which of the following statements is/are incorrect?

    1. Constructor can be called explicitly.
    2. Constructor can be called implicitly.
    3. Destructor is usually called implicitly.
    4. Constructor and destructor functions are not called at all as they are always inlined.
    Solution
    D is incorrect. Constructors and destructors can be both inline functions or non-inline functions.

  5. What is the output of following program?

    #include<iostream>
    using namespace std;
    
    class Point
    {
        Point() { cout << "Constructor called"; }
    };
    
    int main()
    {
       Point x;
       return 0;
    }
    
    1. Compilation error.
    2. Runtime error.
    3. Constructor called.
    4. None of the above.
    Solution
    A is correct. By default all members of a class are private. Since no access specifier is there for Point( ), it is private and it can't be called outside the class when x is constructed in main( ). So the compiler will issue an error message something like "calling a private constructor of class Point".

  6. What is the output of following program?

    #include<iostream>
    using namespace std;
    
    class X
    {
      public:
        int x;
    };
    
    int main()
    {
        X a = { 10 };
        X b = a;
        cout << a.x << " " << b.x;
        return 0;
    }
    
    1. Compilation error
    2. 10 followed by Garbage Value
    3. 10 10
    4. 10 0
    Solution
    C is correct. The following: "X a = {10};" may look like an error, but it works fine. Like structures, class objects with only public data members can be initialized using the { } syntax. The line "X b = a;" calls the copy constructor and is same as "X b(a);". Please note that, if we don't write our own copy constructor, then compiler creates a default copy constructor which does the default memberwise assignment.

  7. What is the output of following program?

    #include<iostream>
    using namespace std;
    
    class Test
    {
      public:
          Test() { cout << "Hello from Test() "; }
    } a;
    
    int main()
    {
        cout << "Main Started ";
        return 0;
    }
    
    1. Main Started
    2. Main Started Hello from Test()
    3. Hello from Test() Main Started
    4. Compilation error: Global objects are not allowed
    Solution
    C is correct. There is a global object a which is constructed before the main functions starts. So the constructor for a is called first, then main( ) execution begins.

  8. What is the output of following program?

    #include<iostream>
    using namespace std;
    
    class Point
    {
        int x;
      public:
        Point(int x) { this->x = x; }
        Point(const Point p) { x = p.x;}
        int getX() { return x; }
    };
    
    int main()
    {
       Point p1(10);
       Point p2 = p1;
       cout << p2.getX();
       return 0;
    }
    
    1. 10
    2. Compilation error: p must be passed by reference
    3. Garbage value
    4. None of the above
    Solution
    B is correct. Objects must be passed by reference in copy constructors. i.e. Copy constructor of class X must have the following signature: X::X(const X& copiee). It cannot be X::X(const X copiee) otherwise it requires copiee to be passed by value to the copy constructor, which in turn will ask for a copy constructor to make the copy, ... resulting in an infinite recursion!

  9. What is the output of following program?

    #include<iostream>
    using namespace std;
    
    class Test
    {
      private:
        int x;
      public:
        Test(int i)
        {
            x = i;
            cout << "conversion ";
        }
    };
    
    int main()
    {
        Test t(20);
        t = 30;
        return 0;
    }
    
    
    1. Compilation error
    2. conversion conversion
    3. conversion
    4. None of the above
    Solution
    B is correct. If a class has a constructor which can be called with a single argument, then the constructor is a conversion constructor because it allows automatic conversion of the argument object to the class' object. A conversion constructor can be called anywhere when the type of the single argument is assigned to the object. In the above code, at the line "t = 30", 30 is converted automatically to a Test object and default assignment is then performed to assign 30 to t.

  10. What is the output of following program?

    #include<iostream>
    using namespace std;
    
    int i;
    
    class A
    {
      public:
        ~A() { i = 10; }
    };
    
    int foo()
    {
        i = 3;
        A x;
        return i;
    }
    
    int main()
    {
        cout << foo() << endl;
        return 0;
    }
    
    1. 0
    2. 3
    3. 10
    4. None of the above
    Solution
    B is correct. While returning from a function, destructors are the last methods to be executed. The destructor for the object "x" is called after the value of i is copied to the return value of the function. So, before destructor could change the value of i to 10, the current value of i gets copied to the main( ) function already.