Q:

Liberar memória em C++

Eu sou obrigado a liberar memória de toda variável que não estarei mais utilizando?
Se sim, como fazer?

A:

Não. Você não tem que liberar memória de variáveis. Nunca, pelo menos de variáveis locais (não variáveis que fazem parte de um outro objeto. Você tem que liberar memória de objetos que são apontados por variáveis. Existe um diferença conceitual importante aí.
Então variáveis por valor nunca precisam liberar seus objetos porque os valores são armazenados na própria área da variável. Estas variáveis podem estar no stack ou dentro de objetos.
Algumas variáveis são por referência. Ou seja, elas guardam um ponteiro para objetos, em geral, em uma área dinâmica da memória chama heap.
Note que mesmo que uma variável por valor esteja dentro de um objeto que está no heap, sua destruição será automática na destruição do objeto. A regra básica é que só é necessário ter uma liberação manual ou automática quando há a presença de ponteiro (tem vários tipos), e de acordo com seu tempo de vida.
RAII e Smart Pointer
Muitos destes objetos gerenciam seu tempo de vida e liberam a memória alocada para eles quando não é mais necessário o seu uso. Ou seja, quando a variável apontadora deixa de existir, o próprio objeto se encarrega de se destruir. Então você não tem que se preocupar.
Quando o objeto não tem esta funcionalidade, ainda é possível automatizar isto com os chamados smart pointers. Isto faz com que você não precise se preocupar com a liberação.
Estas técnicas são sempre recomendadas.
Hoje um programa moderno em C++ dificilmente tem que se preocupar com a liberação de memória manual.
Evidentemente que se você vai construir uma classe nova, provavelmente terá que criar o mecanismo de auto gerenciamento dele. Este é um dos poucos momentos onde precisa lidar com a liberação de memória. Mesmo nestes casos, na maioria das vezes é possível substituir um ponteiro bruto por um ponteiro inteligente (mencionado acima) e não se preocupar também.
Manual:
class Exemplo {
    resource* recurso;
    Exemplo () : recurso(new resource) { }
    ~Exemplo () { delete recurso; }
};

Automático:
class Exemplo {
    std::unique_ptr<resource> recurso;
    Exemplo() : recurso(new resource) { }
};

Fazendo manual
Fora isto, pode fazer uso da liberação manual para fins de aprendizado.
Se alocar a memória manualmente terá que liberar de forma simétrica com a alocação. Se usar a técnica do C usando malloc(), terá que usar um simples free(). Esta forma é considerada obsoleta na maioria das situações em C++.
Se usar o operador new do C++, terá que usar o delete para liberar a memória. Se for um array, usará new[] e delete[]. Mas novamente, só aconselho o uso de um desses controles de memória dentro de classes. A liberação, em geral, ocorrerá dentro do destructor.
Obviamente que em aplicações simples que vão terminar logo ou em alguma alocação que deve durar toda a execução da aplicação não há problemas de vazamento. O fim da aplicação liberará toda memória alocada por ela. O problema só ocorre quando há alocações mais complexas que precisam ser descartadas durante a execução para não congestionar a memória.

