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
Привет, ребята 🙂
Мой вопрос: какова цель явного конструктора и двух перегрузок операторов в этом конкретном случае, и как они используются в примере использования?
Заранее спасибо.
Во-первых, есть две ошибки: p_ не объявлено, и возвращение в operator*
должно быть return *p_
,
Во всяком случае, явным является то, что конструктор не может быть вызван неявно.
Учти это:
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;
}
Вы ожидаете, что это скомпилировать? Оно делает. И он выводит 5. Причина в том, что Пример построен неявно. В основном ex(5)
молча превращается в ex(Example(5))
, Пометка конструктора как явного запрещает такое поведение. Если вы добавили явное в конструктор, это будет ошибка времени компиляции.
Что касается перегрузки операторов, то здесь у вас есть базовый «умный» указатель. (Я бы, вероятно, использовал один из стандартных в C ++ 11 или Boost, если вы не можете использовать компилятор, который имеет стандартизированные, кстати.)
Перегрузка оператора позволяет объекту реагировать на объекты определенным образом. В этой ситуации перегрузка оператора позволяет классу притворяться указателем на тот же тип, который он содержит.
RAII<std::vector<int>> r(new std::vector<int>());
std::cout<<r‐>size()<<std::endl;
r
притворяется std::vector<int>*
через перегрузку оператора здесь. Что действительно происходит, так это то, что он называется:
(r.operator->())->size()
operator->
возвращает std::vector<int>*
итак второе ->
получает доступ к этому и вызывает size()
метод.
Другой пример перегрузки операторов, с которой вы, вероятно, знакомы, это std :: vector’s operator[]
, operator[]
возвращает ссылку на элемент.
Перегрузка оператора, конечно, не всегда используется, чтобы притворяться, что делает уже встроенные вещи. Рассматривать ostream
«s operator<<
, Вместо оператора побитового сдвига он помещает данные в поток.
Дополнительная информация: стандартные умные указатели / повысить умные указатели / RAII / перегрузка оператора.
Да, и ваш код нарушает очень часто верховенства три (или же Правило пяти в C ++ 11). Таким образом, ваш класс будет дважды удалять указатель, если сделана копия.
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.
Других решений пока нет …