In websites such as coolinterview.com, geekinterview.com, you will find plethora of technical interview questions. But all the questions there are posted and answered by the users. You might have found that some questions mentioned there are of any use. Also you will most of the answers not much reliable. We at interviewmantra, extensively research for good interview questions, categorize them according to difficulty, answer each of them in detail, make sure that the answers are correct to the best of our knowledge. Here is the last 5 questions in this series of C++ interview questions. Hope these are of use to you for interview preparation.
6. What’s the knack with vector<bool>?
The std::vector<bool> is a specialization of the std::vector<> class template, i.e., when an object of vector<bool> is created, it uses a specialized and highly optimized version of the vector<> template, instead of instantiating the template for the bool type. The vector<bool> stores boolean data as bits and not as bool variables (which could take a whole byte to store a single true or a false).
The vector<bool> is optimized on space, rather than on speed, unlike the vector<> template. Moreover, this optimization has been forced upon the users because of the specialization. Also, the vector<bool> items are not addressable and the specialization defines the iterator in a form different than that of vector<> which is not random-access. For more info, check here
7. What is the difference between assignment operator and a copy constructor?
As the names suggest, the copy constructor is used to “construct an object”. The new object is an exact copy of another object that is already constructed. The assignment operator is used to “assign an object” with the value(s) of some other object. Hence, the assignment operator is something that comes into action when we have an object to the LHS of the ‘=’ operator and some expression to the RHS.
For Example:
For some type T and “params” for the object’s constructor,
{
T x (params1, ...);
T y (params2, ...);
T z = x; /* Copy : z created with the value of x */
y = x+z; /* Assignment : y gets the value equivalent to x+z */
}
If a programmer doesn’t write a copy constructor or an assignment operator, then the compiler provides one. The copy constructor provided by the compiler does a shallow-copy of the objects and, hence, could lead to problems. And, when the programmer overloads the assignment operator for a particular class, s/he must take care of self-assignment and free the resources before the assignment is done.
8. Why we would use exception handling rather than different return values to signal an error?
The probability of a program failing is never zero and, when when such conditions arise, different steps shall be taken. Two options are – Returning an Error code and using Exception Handling.
Returning an error-code is fine but has some problems associated with it:
- The error-code returned is generally of type “int”. The problem here is that if certain integer values are associated with error-codes, then the function would have to exclude those from the valid return values, which isn’t feasible in all situations.
- Even if the above is feasible, the code would require code to check the return value for each call and this would cause code bloat.
- Some error codes are used to signal that the system is in non-recoverable state and needs to exit. This might not be a good thing to be done at all times, for example, if the code that generates the error and terminates the program is part of a library and is being run as a part of a system that can’t be terminated.
The above problems are not seen while using Exception handling because it separates the error-handling code from the program logic. This also makes the code clean and readable.
9. What is RAII?
Resource Acquisition Is Initialization or RAII is a design pattern that helps in creating objects, on the heap, that are safely destructed. The RAII technique requires a wrapper to be used to hold the resource so that when the wrapper object goes out of scope or an exception is thrown, the resource is freed.
For Example:
#include<exception>
#include<iostream>
#include<string>
struct someClass{};
class Wrap
{
someClass* ptr;
public:
Wrap() : ptr(0){}
Wrap(someClass* obptr): ptr(obptr){}
void setNull()
{
if(ptr)
delete ptr;
ptr=0;
}
void changeRsrc(someClass* obptr)
{
if(ptr)
delete ptr;
ptr=obptr;
}
someClass& operator*() { return *ptr;}
someClass* operator->() { return ptr;}
~Wrap(){ std::cout<<"Destructor\n";delete ptr; ptr=0;}
};
void Foo()
{
/* someClass *somePtr = new someClass; */
Wrap wObj(new someClass);
/* Some Operations on someClass object using wObj */
throw std::exception();
}
int main()
{
try
{
Foo();
}catch(std::exception&){std::cout<<"Exception caught\n";}
}
Here, the class Wrap implements the RAII. When Foo() throws an exception, the wObj, being on the stack, invokes its destructor which frees the memory space taken up by the object of someClass. If the somePtr would have been used, then the space allocated by it would not have been freed.
The auto_ptr is a class template, available in C++, that implements the RAII.
10. What is RTTI? What are its uses?
The RTTI or Run-Time Type Identification is a feature of C++ that helps in storing and retrieving type information of the objects at runtime. This information can be used for safely typecasting objects, and to fetch and utilize the type information to set the flow of the program at runtime.
The RTTI requires the classes in use to be “polymorphic” in nature, which means that there should be at least one virtual function defined in it. The system is used with the help of dynamic_cast<> and the typeid operator.
The typeid operator is available under the “typeinfo” header and can be used to find out the class to which a particular object belongs to, at runtime. The value returned by the operator is implementation-defined and hence, can be different across compilers. Thus, for portability sake, the operator can be used in the following manner:
#include<iostream>
#include<typeinfo>
struct dummyBase
{virtual ~dummyBase(){}};
struct dummyDer: dummyBase{};
void check(dummyBase* a)
{
if(typeid(*a)==typeid(dummyBase))
std::cout<<"It is a dummyBase object\n";
else if(typeid(*a)==typeid(dummyDer))
std::cout<<"It is a dummyDer object\n";
}
int main()
{
dummyDer d;
dummyBase b;
dummyBase*ptr;
ptr=&d;
check(ptr);
ptr=&b;
check(ptr);
}
If only the object information is required and no cast is to be done, then one must use the typeid operator and not the dynamic_cast because the former takes constant-time to return the value.
The dynamic_cast<> operator is what actually utilizes the RTTI system. The dynamic_cast<> is safe because if the cast is not possible, it sets the pointer to NULL instead of returning a bad pointer and in case of a reference, it throws the std::bad_cast exception. The cast knows about the hierarchy of the particular object that helps it do its work correctly and can be used to cast up, down or laterally.
For Example:
#include<iostream>
struct ITop
{
virtual void funcTop()=0;
virtual ~ITop(){}
};
struct ILeft: ITop
{
void funcTop(){ std::cout<<"ILeft funcTop\n";}
virtual void funcLeft()=0;
};
struct IRight: ITop
{
void funcTop(){ std::cout<<"IRight funcTop\n";}
virtual void funcRight()=0;
};
struct Left: ILeft
{
void funcLeft(){ std::cout<<"Left heir\n";}
};
struct Right: IRight
{
void funcRight(){ std::cout<<"Right heir\n";}
};
void Foo(ITop* elem)
{
elem->funcTop();
if(ILeft* ptrL = dynamic_cast<ILeft*>(elem))
ptrL->funcLeft();
else if(IRight* ptrR = dynamic_cast<IRight*>(elem))
ptrR->funcRight();
}
int main()
{
ITop* ptr[]={new Left, new Right};
Foo(ptr[0]);
Foo(ptr[1]);
delete ptr[0];
delete ptr[1];
}
In the above code, the function Foo() checks the type of ‘elem’ and finds out where does the object lie in the hierarchy and accordingly, invokes either the funcLeft() or the funcRight().
Here is one good use of RTTI.

