Comparison 1: Accessing an element
Accessing an element from an array stored as a single contiguous chunk of memory will be more efficient. This is because each access will only require a single level of indirection. You presumably will have a pointer to the first element of the array, and you can calculate an offset from there based on the dimensions of the array.
With a jagged array, more indirection is involved. First you calculate the offset to the row that you want and retrieve the address there. Using that address, you calculate the offset to the column you want. And if you have a higher dimensional array, more levels of indirection will be involved.
Comparison 2: Cache Efficiency
Having a single contiguous chunk of memory will obviously be more cache efficient. Spatial locality is as good as its going to get.
A jagged array will be less cache efficient for obvious reasons - the memory for each row is not guaranteed to be adjacent to the memory for its neighboring rows.
Comparison 3: Initialization
A single chunk of memory is easy to allocate and initialize. Calculate how much memory you need, allocate it, and a simple loop will initialize it.
A jagged array is slightly more complicated to allocate and initialize. First you allocate an array that will hold pointers to the rows. Then for each row you allocate memory for the columns in that row. You continue in the same fashion for higher dimensional array. I've seen many new programmers fail at this task because they didn't realize each row needed to be allocated as well.
Comparison 4: Flexibility
Using a single chunk of memory makes it impossible to have rows of differing sizes unless you specifically account for this by storing the row sizes separately or using some other complicated scheme to achieve this. This can result in wasted memory if you won't completely fill each row.
Jagged arrays are very flexible. Since each row is allocated separately they can each be a different size. There is no need to waste space.
Comparison 5: Adding new rows
Adding a new row to a single chunk of memory will only be a problem if there isn't enough contiguous space available after the end of the array. In this case a reallocation will result in the entire array being moved in memory.
Adding a row to a jagged array will not be a problem 99% of the time.
Comparison 6: Adding new columns
Oh dear. Adding a new column to single contiguous array is quite a task. Many items will need to be moved around.
Adding a column to a jagged array isn't nearly as bad. Plus, you can add a column to a single row if you want. There's no need to change the size of every row.
(Disclaimer: Obviously I'm assuming row-major ordering here.)
A simple chunk of memory is usually the most efficient way to store data. If you are writing a crucial algorithm that requires extreme efficiency, you will probably want to use a simple contiguous array unless you have a compelling reason not to.
However, in most code extreme efficiency isn't needed. If you're responding to an button event in a form, or some timer that ticks once every couple hundred milliseconds or so, efficiency probably isn't your primary concern. Usually its better to use a more robust, easily modifiable data structure. Try to write code that is easy to read, maintain, and extend. Worry about efficiency only when and where it is a problem.