Some things to note : - A you said there are `std::min(m,n)/2;` rings. - the ring `R(r, p)` has `2*(r+p-2)` elements. - the top left of the ring has always coordinates `(x,x)`. This is visible in your code :) `j = ring_i; v_ring.push_back(mat[ring_i][j]);` - Your code is using a relatively efficient amount of memory for the in-place transformation, and running in O(m*n) time, which is the best possible. - A performance improvement will be to use a single vector for the data in the matrix such that `m(x,y) = m.data[x * cols + y]` **Can we do it differently ?** Given the local coordinates system where (0, 0) is the top left of the ring [![qt example of this coordinate][1]][1] A coordinate `(i,j), 0<=i<w, 0<=j<h, j == 0 || i == 0` on a side of a ring, can be moved by one position using the function std::pair<int, int> rotated_local_next(int i, int j, int h, int w) { if(j == 0) //top , special case top-right { return i == w-1 ? {i, ++j} : {++i, j}; } if(i == w-1) //right, special case bottom-right { return j == h-1 ? {--i, j} : {i, ++j}; } if(j == h-1) //bottom, special case bottom-left { return i == 0 ? {i, --j} : {--i, j}; } if(i == 0) //left, special case top-left { return j == 0 ? {++i, j} : {i, --j}; } // unreachable } You can now implement in matrix coordinates std::pair<int, int> rotated_matrix_next(int x, int y, int ring_i, int n, int m) { // remember ring_i is now auto local_point = rotated_local_next(x-ring_i, y-ring_i, n-2*(ring_i+1), m-2*(ring_i+1)) return {local_point.first + ring_i, local_point.second + ring_i}; } All you need to do now is to implement iterators satisfying [MoveAssignable and MoveConstructible][2]. The following is just pseudocode class ring_iterator { public: ptr_matrix p; int x, int y, int ring; // Forward ring_iterator operator++() { posnext = rotated_matrix_next(x, y, ring, p->size(), (*p)[0].size()); ring_iterator next_iter = *this; next_iter.x = posnext.first; next_iter.y = posnext.second; } // Swappable void swap(ring_iterator& other) { int& mine = (*p)[x][y]; int& theirs = other.(*p)[x][y]; int tmp = mine; mine = theirs; theirs = tmp; } // usually required reference operator*() { return (*p)[x][y]; } pointer operator->() { &((*p)[x][y]); } }; Once begin(), end() is implemented your code will become for(auto ring_i=0; ring_i<n_rings; ++ring_i){ RingWiew view(&m, m.size(), m[0].size(), ring_i); int r_modulo = r % view.ringNumberOfElements(); std::rotate(view.begin(),std::advance(view.begin(), r_modulo),v_ring.end()); } [1]: https://i.sstatic.net/L3AqA.png [2]: http://en.cppreference.com/w/cpp/algorithm/rotate