{"id":105908,"date":"2021-11-12T07:00:00","date_gmt":"2021-11-12T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=105908"},"modified":"2025-03-24T16:58:09","modified_gmt":"2025-03-24T23:58:09","slug":"20211112-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20211112-00\/?p=105908","title":{"rendered":"Another way of looking at C++ reverse iterators"},"content":{"rendered":"<p>C++ has this thing called a <code>reverse_iterator<\/code> that takes a regular iterator and goes in the opposite direction. You might think that an iterator and its reverse point to the same thing, and it&#8217;s just the increment and decrement operators that are reversed, but that&#8217;s not true. An iterator and its reverse point to <i>different things<\/i>.<\/p>\n<p>This reason for this comes down to a quirk of the C++ language: You are allowed to have a pointer &#8220;one past the end&#8221; of a collection, but you are not allowed to have a pointer &#8220;one before the beginning&#8221; of a collection.<\/p>\n<p>When moving forward through a collection, you can use the &#8220;one past the end&#8221; pointer as the sentinel that means &#8220;you&#8217;re done.&#8221;<\/p>\n<table id=\"p20211112_forward_iterator_animation\" style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border-bottom: solid 1px transparent; width: 4em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: dotted 1px currentcolor; width: 4em;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nbegin<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nend<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>But you don&#8217;t have such a luxury when going backward:<\/p>\n<table id=\"p20211112_reverse_iterator_animation\" style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border-bottom: solid 1px transparent; width: 4em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: dotted 1px currentcolor; width: 4em;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\noops<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nbegin<\/div>\n<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>You want to create an <i>end<\/i> sentinel value immediately before the first element, but you can&#8217;t because the C++ language forbids it.<\/p>\n<p>The standard library finesses the problem by making the reverse iterator &#8220;off by one&#8221;: The element referenced by the iterator is the one <i>before<\/i> the one it nominally points to.<\/p>\n<table id=\"p20211112_reverse_iterator_animation2\" style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border-bottom: solid 1px transparent; width: 4em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: dotted 1px currentcolor; width: 4em;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nend<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nok<\/div>\n<\/td>\n<td>\n<div style=\"display: none;\">\u2191<br \/>\nbegin<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>This off-by-one behavior is a bit tricky to wrap your brain around, but here&#8217;s a way of looking at it that&#8217;s a bit less wacky: View the pointer as pointing, not at the center of an element, but at its start. When iterating forward, you look to the element in <i>front<\/i> of the pointer, and when iterating backward, you look to the element in <i>back<\/i> of the pointer. In both cases, you look in the direction of motion.<\/p>\n<table id=\"p20211112_forward_iterator_animation2\" style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border-bottom: solid 1px transparent; width: 4em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: dotted 1px currentcolor; width: 4em;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>\n<div style=\"display: none; text-align: left;\"><span style=\"position: relative; left: -1ex; top: 0;\">\u2191begin<\/span><\/div>\n<\/td>\n<td>\n<div style=\"display: none; text-align: left;\"><span style=\"position: relative; left: -1ex;\">\u2191ok<\/span><\/div>\n<\/td>\n<td>\n<div style=\"display: none; text-align: left;\"><span style=\"position: relative; left: -1ex;\">\u2191ok<\/span><\/div>\n<\/td>\n<td>\n<div style=\"display: none; text-align: left;\"><span style=\"position: relative; left: -1ex;\">\u2191ok<\/span><\/div>\n<\/td>\n<td>\n<div style=\"display: none; text-align: left;\"><span style=\"position: relative; left: -1ex;\">\u2191ok<\/span><\/div>\n<\/td>\n<td>\n<div style=\"display: none; text-align: left;\"><span style=\"position: relative; left: -1ex;\">\u2191ok<\/span><\/div>\n<\/td>\n<td>\n<div style=\"display: none; text-align: left;\"><span style=\"position: relative; left: -1ex;\">\u2191end<\/span><\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table id=\"p20211112_reverse_iterator_animation3\" style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border-bottom: solid 1px transparent; width: 4em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: dotted 1px currentcolor; width: 4em;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td>\n<div style=\"display: none; text-align: right;\"><span style=\"position: relative; left: 1ex;\">end\u2191<\/span><\/div>\n<\/td>\n<td>\n<div style=\"display: none; text-align: right;\"><span style=\"position: relative; left: 1ex;\">ok\u2191<\/span><\/div>\n<\/td>\n<td>\n<div style=\"display: none; text-align: right;\"><span style=\"position: relative; left: 1ex;\">ok\u2191<\/span><\/div>\n<\/td>\n<td>\n<div style=\"display: none; text-align: right;\"><span style=\"position: relative; left: 1ex;\">ok\u2191<\/span><\/div>\n<\/td>\n<td>\n<div style=\"display: none; text-align: right;\"><span style=\"position: relative; left: 1ex;\">ok\u2191<\/span><\/div>\n<\/td>\n<td>\n<div style=\"display: none; text-align: right;\"><span style=\"position: relative; left: 1ex;\">ok\u2191<\/span><\/div>\n<\/td>\n<td>\n<div style=\"display: none; text-align: right;\"><span style=\"position: relative; left: 1ex;\"><span style=\"right: 1ex;\">begin\u2191<\/span><\/span><\/div>\n<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Now the off-by-one behavior is easier to see. A pointer when interpreted as a forward iterator looks forward one element, but when interpreted as a reverse iterator looks backward one element.<\/p>\n<table id=\"p20211112_combo_iterator_animation\" style=\"border-collapse: collapse; text-align: center; overflow: hidden;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border-bottom: solid 1px transparent; width: 4em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: solid 1px currentcolor; width: 4em;\">\u2022<\/td>\n<td style=\"border: dotted 1px currentcolor; width: 4em;\">\u00a0<\/td>\n<\/tr>\n<tr style=\"display: none;\">\n<td style=\"text-align: right; position: relative; left: .25em;\">\n<div style=\"position: absolute; right: 1em; top: .25em;\">rev<br \/>\nend<\/div>\n<div>\u2191<\/p>\n<\/div>\n<\/td>\n<td style=\"text-align: left; position: relative;\">\n<div style=\"position: absolute; left: .5em; top: .25em;\">fwd<br \/>\nbegin<\/div>\n<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"display: none; xfont-size: 80%;\">\n<td>&nbsp;<\/td>\n<td style=\"text-align: right; position: relative; left: .25em;\">\n<div style=\"position: absolute; right: 1em; top: .25em;\">rev<br \/>\nok<\/div>\n<div>\u2191<\/p>\n<\/div>\n<\/td>\n<td style=\"text-align: left; position: relative;\">\n<div style=\"position: absolute; left: .5em; top: .25em;\">fwd<br \/>\nok<\/div>\n<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"display: none; xfont-size: 80%;\">\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"text-align: right; position: relative; left: .25em;\">\n<div style=\"position: absolute; right: 1em; top: .25em;\">rev<br \/>\nok<\/div>\n<div>\u2191<\/p>\n<\/div>\n<\/td>\n<td style=\"text-align: left; position: relative;\">\n<div style=\"position: absolute; left: .5em; top: .25em;\">fwd<br \/>\nok<\/div>\n<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"display: none; xfont-size: 80%;\">\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"text-align: right; position: relative; left: .25em;\">\n<div style=\"position: absolute; right: 1em; top: .25em;\">rev<br \/>\nok<\/div>\n<div>\u2191<\/p>\n<\/div>\n<\/td>\n<td style=\"text-align: left; position: relative;\">\n<div style=\"position: absolute; left: .5em; top: .25em;\">fwd<br \/>\nok<\/div>\n<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"display: none; xfont-size: 80%;\">\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"text-align: right; position: relative; left: .25em;\">\n<div style=\"position: absolute; right: 1em; top: .25em;\">rev<br \/>\nok<\/div>\n<div>\u2191<\/p>\n<\/div>\n<\/td>\n<td style=\"text-align: left; position: relative;\">\n<div style=\"position: absolute; left: .5em; top: .25em;\">fwd<br \/>\nok<\/div>\n<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"display: none; xfont-size: 80%;\">\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"text-align: right; position: relative; left: .25em;\">\n<div style=\"position: absolute; right: 1em; top: .25em;\">rev<br \/>\nok<\/div>\n<div>\u2191<\/p>\n<\/div>\n<\/td>\n<td style=\"text-align: left; position: relative;\">\n<div style=\"position: absolute; left: .5em; top: .25em;\">fwd<br \/>\nok<\/div>\n<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"display: none; xfont-size: 80%;\">\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"text-align: right; position: relative; left: .25em;\">\n<div style=\"position: absolute; right: 1em; top: .25em;\">rev<br \/>\nbegin<\/div>\n<div>\u2191<\/p>\n<\/div>\n<\/td>\n<td style=\"text-align: left; position: relative;\">\n<div style=\"position: absolute; left: .5em; top: .25em;\">fwd<br \/>\nend<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\n<script>\n(function() {\n  var single = (function() {\n    var colorRows = [];\n    var arrowRows = [];\n    var length;\n    function addTable(id, start0, reverse0, start1, reverse1) {\n        var table = document.getElementById(id);\n        var cells = table.rows[0].cells;\n        length = cells.length - 1;\n        var row = Array.prototype.slice.call(cells, start0, start0 + length);\n        if (reverse0) row.reverse();\n        colorRows.push(row);\n        cells = table.rows[1].cells;\n        row = Array.prototype.slice.call(cells, start1, start1 + length);\n        if (reverse1) row.reverse();\n        arrowRows.push(row);\n    }\n    addTable(\"p20211112_forward_iterator_animation\", 1, false, 1, false);\n    addTable(\"p20211112_forward_iterator_animation2\", 1, false, 1, false);\n    addTable(\"p20211112_reverse_iterator_animation\", 0, true, 0, true);\n    addTable(\"p20211112_reverse_iterator_animation2\", 0, true, 1, true);\n    addTable(\"p20211112_reverse_iterator_animation3\", 0, true, 0, true);\n    var current = length - 1;\n    var hold = false;\n    function step() {\n        if (hold) {\n            hold = false;\n        } else {\n            colorRows.forEach(function (row) {\n                row[current].style.backgroundColor = \"inherit\";\n            });\n            arrowRows.forEach(function (row) {\n                row[current].firstElementChild.style.display = \"none\";\n            });\n            ++current;\n            hold = (current == length - 1);\n            if (current == length) { current = 0; }\n            colorRows.forEach(function (row) {\n                var cell = row[current];\n                cell.style.backgroundColor = cell.innerText ? \"gray\" : \"inherit\";\n            });\n            arrowRows.forEach(function (row) {\n                row[current].firstElementChild.style.display = \"block\";\n            });\n        }\n    }\n    return step;\n  })();\n  var bidir = (function() {\n    var tbl = document.getElementById(\"p20211112_combo_iterator_animation\");\n    var rows = Array.prototype.slice.call(tbl.rows, 1, tbl.rows.length);\n    var indices = [ 0, 1, 2, 3, 4, 5, 6, 6, 6, 5, 4, 3, 2, 1, 0, 0 ];\n    var current = indices.length - 1;\n    function step() {\n        rows[indices[current]].style.display = \"none\";\n        ++current;\n        if (current == indices.length) current = 0;\n        rows[indices[current]].style.display = \"\";\n    }\n    return step;\n  })();\n    function step() {\n        single();\n        bidir();\n    }\n    step();\n    setInterval(step, 500);\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s the same thing, just going in the opposite direction, right?<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-105908","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It&#8217;s the same thing, just going in the opposite direction, right?<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105908","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=105908"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105908\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=105908"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=105908"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=105908"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}