You're program seemed to segfault on this line.
m_grid[col][row] = nullptr;
It's because you're indexing the matrix out of range (which is undefined behaviour) as you got the row and column backwards. You should be doing m_grid[row][col] instead.
Note that [] doesn't do range check, so if you want to range checking you can use .at().
Another issue is this line.
m_window( *new sf::RenderWindow(sf::VideoMode(COLS*CELL_SIZE,
ROWS*CELL_SIZE),"Test") )
Is there a reason why you're initialising m_window is like this? You could simply make m_window not a reference, and just initialise it normally.
m_window( sf::VideoMode(COLS*CELL_SIZE,
ROWS*CELL_SIZE),"Test")
This way you avoid the unnecessary dynamic allocation.
When you do
need to use dynamic allocation. It's best to avoid explicit new when possible, as there's usually better alternatives, such as unique_ptr and shared_ptr. Learn about RAII, and you can reduce error-prone manual resource management.
Another issue is that your Life class is has no virtual destructor. Polymorphic base classes need one to prevent undefined behaviour. It's quite simple to so.
class Life : public sf::Drawable
{
public:
//....
virutal ~Life() = default;
};
As usual when you're defining destructors, you should be aware of the rule of 5.
Well that's the major issues, onto the very minor things.
Minor things that you may want to know. Firstly sf::Noncopyable also deletes the move functions as well as copy which may not be what you want. Secondly, it is preferably for the constants at the top (ROWS) to be constexpr instead of const, so you don't get compiler errors down the road. Thirdly, if you want scoped enums you can you enum classes as it also provides strong typing. Fourthly, having both virtual and override in a function declaration is redundant as you cannot override a non-virtual function, so you can simply just have override.