0
template<typename T>
class RAII
{
public:

    explicit RAII( T* p = 0 ): p_(p){}

    ~RAII() {delete p_;}

    T& operator*() const { return p_;} 
    T* operator‐>() const{ return p_;}
};

//Usage example:
{
      RAII<std::vector<int>> r(new std::vector<int>());
      std::cout<<r­‐>size()<<std::endl;
} // The std::vector<int> is automatically deallocated

Hi guys :)

My question: What is the purpose of the explicit constructor and the two operator overloadings in this specific case, and how are they used in the usage example?

Thanks in advance.

manlio
  • 18,345
  • 14
  • 76
  • 126

1 Answers1

0

First thing: there's two errors: p_ is not declared, and the return in operator* should be return *p_.


Anyway, the explicit is so the constructor can't be called implicitly.

Consider this:

class Example {
public:
    int x;
    Example(int x) : x(x) {}
};

function ex(const Example& e) {
    std::cout << e.x;
}

int main() {
    ex(5);
    return 0;
}

Do you expect this to compile? It does. And it outputs 5. The reason is that an Example is implicitly constructed. Basically the ex(5) is silently turned into ex(Example(5)). Marking a constructor as explicit forbids this behavior. If you added an explicit to the constructor, this would be a compile time error.


As for the operator overloading, what you have here is a basic 'smart' pointer. (I would probably use one of the standard ones in C++11 or boost if you can't use a compiler that has the standardized ones by the way.)

Operator overloading allows an object to react to objects in a specific way. In this situation, operator overloading is allowing the class to pretend to be a pointer over the same type that it's containing.

RAII<std::vector<int>> r(new std::vector<int>());
std::cout<<r­‐>size()<<std::endl;

r is pretending to be a std::vector<int>* via operator overloading here. What is really happening is that it's being called as:

(r­.operator->())->size()

operator-> returns a std::vector<int>*, so the second -> is accessing that and calling the size() method.

Another example of operator overloading that you're probably familiar with is std::vector's operator[]. operator[] returns a reference to an element.

Operator overloading is of course not always used to pretend to be doing already built in things. Consider ostream's operator<<. Rather than the bitshift operator, it puts data into a stream.


More information: standard smart pointers / boost smart pointers / RAII / operator overloading.

Oh, and your code violates the very commonly adhered to rule-of-three (or rule of five in C++11). As it is, your class will double delete a pointer if a copy is made.

RAII<int> p(new int)
RAII<int> q = p;
//when q's destructor runs, bad bad things will happen since p's destructor already deleted the int.
Community
  • 1
  • 1
Corbin
  • 33,060
  • 6
  • 68
  • 78
  • So the purpose of the operator overloadings, is to use "r" as a pointer with the -> operator or as a reference with the * operator? I understand the difference between a implicit and explicit constructor, but I'm still not clear about the purpose of this line: "explicit RAII( T* p = 0 ): p_(p){}". What is the explicit constructor doing with p and p_ ? –  Jan 09 '13 at 09:50
  • @user1960649 For your first question: Yes, pretty much. As for your second question: that's called an initializer list. It has nothing to do with the constructor being explicit. It just means that p_ is initialized to whatever the value of p is. – Corbin Jan 09 '13 at 09:56