This is more or less what std::vector does, though that one is implemented with significantly greater generality in mind, so it's a bit hard for a newcomer to read the source of any library implementation (especially given the usually nightmarish naming conventions used in standard library code).
Here's baby's first dynamic array:
class MyArray
{
float * buf;
std::size_t size;
public:
explicit MyArray(std::size_t s) : buf(new float[s]), size(s) { }
~MyArray() { delete[] buf; }
// Copying and reassigning is tricky! We disallow it for now.
MyArray(MyArray const &) = delete;
MyArray & operator=(MyArray const &) = delete;
std::size_t size() const { return size; }
float & operator[](std::size_t i) { return buf[i]; }
float const & operator[](std::size_t i) const { return buf[i]; }
};
This is exception-safe: the only time an exception could happen is in the initializer list of the constructor, and there is only one such occasion (new). Should an exception happen, nothing will be leaked, since nothing else has been allocated at that point.
Usage:
MyArray a(20);
a[4] = 6.3;
A more advanced version would include a resize() feature; for that, you'll have to allocate and copy (say):
void resize(std::size_t n)
{
float * tmp = new float[n];
std::copy(buf, buf + std::min(size, n), tmp); // I assume this doesn't throw
delete[] buf;
buf = tmp;
size = n;
}
Once you understand what the assignment operator is supposed to do, you can use an idea very similar to that of resize() to assign one MyArray to another.