Use enum whenever you have a finite set of states that are associated with something you can name. Tile types are a prime example for this. In C++11, I recommend using typesafe enums (i.e. enum struct/class).
To reduce the required size, you can specify the underlying type. For example, for 256 distinct types or less, you could use unsigned char, which only takes one byte per value.
enum struct TileType : unsigned char
{
Empty,
Block,
Grass,
...
};
And I would use a 1D std::vector and compute 1D indices from 2D indices, it's easier to manage.