{"id":108577,"date":"2023-08-09T07:00:00","date_gmt":"2023-08-09T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=108577"},"modified":"2023-08-09T07:21:07","modified_gmt":"2023-08-09T14:21:07","slug":"20230809-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230809-00\/?p=108577","title":{"rendered":"Inside STL: The deque, design"},"content":{"rendered":"<p>The C++ standard library <code>deque<\/code> is a double-ended queue that supports adding and removing items efficiently at either the front or the back.<\/p>\n<p>All three of the major implementations of the C++ standard library use the same basic structure for a deque, but they vary in both policy and implementation details.<\/p>\n<p>First, let&#8217;s design a simple version of a deque that stores its elements in an array.<\/p>\n<pre>template&lt;typename T&gt;\r\nstruct simple_deque\r\n{\r\n    T* elements;\r\n    T* first;\r\n    T* last;\r\n    size_t capacity;\r\n};\r\n<\/pre>\n<p>For example, a deque of three integers might look like this:<\/p>\n<table style=\"border-collapse: collapse; position: relative;\" title=\"See text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"position: relative; left: -1ex;\" colspan=\"3\">\u2193 first<\/td>\n<td style=\"position: relative; left: -1ex;\" colspan=\"2\">\u2193 last<\/td>\n<\/tr>\n<tr>\n<td>elements<\/td>\n<td>\u2192<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">1<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">3<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">?<\/td>\n<\/tr>\n<tr>\n<td colspan=\"10\">capacity = 8<\/td>\n<\/tr>\n<tr>\n<td colspan=\"10\">size = last \u2212 first = 3<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The <code>elements<\/code> points to an array whose length is given by the <code>capacity<\/code> member&#8217;s value of 8. In that array, the first three elements are not in use, but which could be used in the future. We&#8217;ll call them <i>spares<\/i>. Next come three elements holding the values 1, 2, and 3, followed by two more spares. The first element in use (1) is pointed to by <code>first<\/code>, and one past the last element in use is pointed to by <code>last<\/code>.<\/p>\n<p>With this design, the four basic deque operations are straightforward:<\/p>\n<ul>\n<li>Remove from front: Increment <code>first<\/code>.<\/li>\n<li>Remove from back: Decrement <code>last<\/code>.<\/li>\n<li>Add to front: Decrement <code>first<\/code> and store the new value there.<\/li>\n<li>Add to back: Store the new value at <code>last<\/code>, and then increment <code>last<\/code>.<\/li>\n<\/ul>\n<p>When you run out of spares, you have a few choices.<\/p>\n<ul>\n<li>If there is a spare at the opposite end, you can move the elements over, so that they consume one or more of the spares at the opposite end, and free up spares on the end you are trying to expand.<\/li>\n<li>If there are no spares anywhere, then you need to allocate a new, bigger array and then move the existing elements out of the old array into the new one, leaving space to be used as new spares.<\/li>\n<\/ul>\n<p>Now, this is an inefficient data structure because both of the alternatives for freeing up spares are <var>O<\/var>(<var>n<\/var>), which is a problem when the dequeue gets large.<\/p>\n<p>To solve this, the implementations don&#8217;t use a giant array. Instead, the giant array is chopped up into fixed-sized blocks. That way, expanding the array entails just allocating a new block.<\/p>\n<table style=\"border-collapse: collapse; position: relative;\" title=\"See text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"position: relative; left: -1ex;\" colspan=\"5\">\u2193 first<\/td>\n<td style=\"position: relative; left: -1ex;\" colspan=\"2\">\u2193 last<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">?<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">1<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">?<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em; text-align: center;\">?<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center;\" colspan=\"2\">block<\/td>\n<td>&nbsp;<\/td>\n<td style=\"text-align: center;\" colspan=\"2\">block<\/td>\n<td>&nbsp;<\/td>\n<td style=\"text-align: center;\" colspan=\"2\">block<\/td>\n<td>&nbsp;<\/td>\n<td style=\"text-align: center;\" colspan=\"2\">block<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>This is the same diagram we had earlier, except that instead of eight contiguous elements, we have four blocks, each of which holds two elements.<\/p>\n<p>The four basic deque operations are still the same. It&#8217;s just that incrementing and decrementing the <code>first<\/code> and <code>last<\/code> pointers is more complicated because they have to know to jump to the next block when incrementing past the end of the current block, or jump to the previous block when decrementing past the beginning of the current block.<\/p>\n<p>If you need to expand the array, you can allocate a new block and add it to the beginning or end. No elements need to be moved.<\/p>\n<p>Next time, we&#8217;ll dig into the implementations. That&#8217;s where things get messy.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>An array of (pointers to) arrays.<\/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-108577","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>An array of (pointers to) arrays.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108577","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=108577"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108577\/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=108577"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=108577"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=108577"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}