{"id":102,"date":"2009-10-16T05:55:40","date_gmt":"2009-10-16T05:55:40","guid":{"rendered":"http:\/\/www.mrericsir.com\/blog\/?p=102"},"modified":"2023-07-14T19:31:19","modified_gmt":"2023-07-14T19:31:19","slug":"c-2d-generic-array-class","status":"publish","type":"post","link":"https:\/\/www.mrericsir.com\/blog\/technology\/c-2d-generic-array-class\/","title":{"rendered":"C++ 2D generic array class"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Recently I found myself writing a templated 2d array class in C++ for a personal project, and I thought I&#8217;d share. If you want to learn about 2d arrays or templates in C++, this article should provide a little insight for you. On the other hand, if you&#8217;re an experienced C++ developer, you should be able to slam out a class just like mine in minutes, but the code is at the end so you don&#8217;t have to.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Yes, you&#8217;re welcome to use this code or expand on it for your own project. It&#8217;s available under a BSD license which should be appropriate for most projects.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Usage<\/strong><br>The Array2D class can be used like so:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/ Create a 3x5 array of longs and fill it with zeroes.\nArray2D&lt;long&gt; myArray( 3, 5 );\nmyArray.setAll( 0 );\n\n\/\/ Now we're going to set the 0, 0 element to 23 and then retrieve it.\nmyArray.set( 23, 0, 0 );\nlong twentyThree = myArray.get( 0, 0 );<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Make sense? Let&#8217;s walk through a few key parts.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Template<\/strong><br>Back in the old days, you&#8217;d have to write your own list class for each data type you wanted to put in a list. For example you might have ListInt and ListString to store ints and strings, respectively. But nowdays you can just have one generic List class that stores any data type.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In C++ the Standard Template Library classes take care of a lot of data types for you. For lists we typically use the vector class and instantiate it with vector&lt;int&gt; for a list integers and vector&lt;string&gt; for a list of strings. It&#8217;s a real time saver. Yay for lazy programmers!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We make our Array2D class generic by using a C++ template. Here&#8217;s how it works.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">template &lt;class T&gt;\nclass Array2D\n{<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is what tells the compiler than you have to instantiate the class with a specific type, for example MyClass; instead of just MyClass;. We&#8217;re calling our data type T. Now how do we use it? Here&#8217;s how:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Data storage<\/strong><br>The data is stored as a double pointer of type T. This double pointer mechanism seemskind of clumsy, but it&#8217;s the only way to create a 2D array in C++.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">T** data;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Our data is actually stored as [y][x] because that felt more comfortable to me. It&#8217;s just a convention I happen to like, I swear I&#8217;m not dyslexic.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Memory management<\/strong><br>I found myself copying and pasting allocation, deallocation, etc. code just to use a damn 2D array, which it what inevitably led to the code we have here today.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">data = new T*[height];\nfor ( int i = 0; i &lt; height; i++ )\n{\n\tdata[i] = new T[width];\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is actually fairly straightforward &#8212; we&#8217;re creating one array for the height, which contains pointers to array for the width. Pretend you just created y vectors of size x.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Deallocation is pretty much the same, so I won&#8217;t go into it here. Basically we just delete everything we created here, but in the opposite order.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Accessing data<\/strong><br>How do we change and retrieve data in our class? Easily.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">T get( const int&amp; x, const int&amp; y )\n{\n\treturn data[y][x];\n}\n\nvoid set( const T&amp; t, const int&amp; x, const int&amp; y )\n{\n\tdata[y][x] = t;\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Internally, the data access looks like you would expect for a 2D array. There&#8217;s also methods for retrieving the dimensions so the user can iterate over it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We only expose a getter and setter, never a pointer to the actual data. Otherwise the user could delete a row and the whole program would come crashing down.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One other note &#8212; this class was designed for speed. If you&#8217;re wondering what&#8217;s up with the paramters like &#8220;const int&amp; z&#8221; it&#8217;s pretty simple. It tells the compiler that instead of making a copy, you can pass a reference to the same data into the function. The const means that we won&#8217;t change that value inside the function (we would get a compiler error if we did) so there&#8217;s no need to worry. This gives us a little extra speed because pass by reference is a little faster than pass by value, since no copy is made.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Okay! I hope I didn&#8217;t lose any C++ beginners there. If you&#8217;re lost, play with the code because that&#8217;s the best way to learn. Hell, add some more features just for fun:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Features you might want to add:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>What about a 3D array, a 4D array, etc?<\/li>\n\n\n\n<li>Matrix functions: matrix addition, cross product, dot product&#8230;<\/li>\n\n\n\n<li>Overload the square brackets for easy access<\/li>\n\n\n\n<li>Resize funtion<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Okay, now on to the source listing!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Array2D.h<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/ Copyright (c) 2009, Eric Gregory\n\/\/ All rights reserved.\n\/\/\n\/\/ Redistribution and use in source and binary forms, with or without\n\/\/ modification, are permitted provided that the following conditions are met:\n\/\/    * Redistributions of source code must retain the above copyright\n\/\/      notice, this list of conditions and the following disclaimer.\n\/\/    * Redistributions in binary form must reproduce the above copyright\n\/\/      notice, this list of conditions and the following disclaimer in the\n\/\/      documentation and\/or other materials provided with the distribution.\n\/\/    * Neither the name of Eric Gregory nor the\n\/\/      names of its contributors may be used to endorse or promote products\n\/\/      derived from this software without specific prior written permission.\n\/\/\n\/\/ THIS SOFTWARE IS PROVIDED BY ERIC GREGORY ''AS IS'' AND ANY\n\/\/ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n\/\/ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n\/\/ DISCLAIMED. IN NO EVENT SHALL ERIC GREGORY  BE LIABLE FOR ANY\n\/\/ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n\/\/ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n\/\/ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n\/\/ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n\/\/ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n\/\/ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n#ifndef ARRAY2D_H_\n#define ARRAY2D_H_\n\ntemplate &lt;class T&gt;\nclass Array2D\n{\npublic:\n\n\tArray2D()\n\t{\n\t\tdata = NULL;\n\t\twidth = 0;\n\t\theight = 0;\n\t}\n\n\tArray2D( const int&amp; width, const int&amp; height )\n\t{\n\t\tdata = NULL;\n\t\tallocate( width, height );\n\t}\n\n\t~Array2D()\n\t{\n\t\tdeallocate();\n\t}\n\n\tT get( const int&amp; x, const int&amp; y )\n\t{\n\t\treturn data[y][x];\n\t}\n\n\tvoid set( const T&amp; t, const int&amp; x, const int&amp; y )\n\t{\n\t\tdata[y][x] = t;\n\t}\n\n\tvoid setAll( const T&amp; t )\n\t{\n\t\tfor ( int y = 0; y &lt; height; y++ )\n\t\t{\n\t\t\tfor ( int x = 0; x &lt; width; x++ )\n\t\t\t{\n\t\t\t\tdata[y][x] = t;\n\t\t\t}\n\t\t}\n\t}\n\n\tint getWidth()\n\t{\n\t\treturn width;\n\t}\n\n\tint getHeight()\n\t{\n\t\treturn height;\n\t}\n\nprivate:\n\n\tvoid allocate( const int&amp; width, const int&amp; height )\n\t{\n\t\t\/\/ Remember dimensions.\n\t\tthis-&gt;width = width;\n\t\tthis-&gt;height = height;\n\n\t\t\/\/ Allocate.\n\t\tdata = new T*[height];\n\t\tfor ( int i = 0; i &lt; height; i++ )\n\t\t{\n\t\t\tdata[i] = new T[width];\n\t\t}\n\t}\n\n\tvoid deallocate()\n\t{\n\t\tif ( NULL == data )\n\t\t{\n\t\t\t\/\/ Nothing to do.\n\t\t\treturn;\n\t\t}\n\n\t\t\/\/ Free the memory.\n\t\tfor ( int i = 0; i &lt; height; i++ )\n\t\t{\n\t\t\tdelete[] data[i];\n\t\t}\n\t\tdelete[] data;\n\n\t\t\/\/ Reset.\n\t\twidth = 0;\n\t\theight = 0;\n\t\tdata = NULL;\n\t}\n\n\tint width;\n\tint height;\n\tT** data;\n};\n\n#endif \/* ARRAY2D_H_ *\/<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Recently I found myself writing a templated 2d array class in C++ for a personal project, and I thought I&#8217;d share. If you want to [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_eb_attr":"","slim_seo":{"title":"C++ 2D generic array class - MrEricSir.com","description":"Recently I found myself writing a templated 2d array class in C++ for a personal project, and I thought I'd share. If you want to learn about 2d arrays or templ"},"autoblue_enabled":true,"autoblue_custom_message":"","autoblue_shares":[],"autoblue_post_url":"","autoblue_publish_document":false,"footnotes":""},"categories":[3],"tags":[40,63,64,62],"class_list":["post-102","post","type-post","status-publish","format-standard","hentry","category-technology","tag-c","tag-generic","tag-oop","tag-template"],"_links":{"self":[{"href":"https:\/\/www.mrericsir.com\/blog\/wp-json\/wp\/v2\/posts\/102","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mrericsir.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mrericsir.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mrericsir.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mrericsir.com\/blog\/wp-json\/wp\/v2\/comments?post=102"}],"version-history":[{"count":13,"href":"https:\/\/www.mrericsir.com\/blog\/wp-json\/wp\/v2\/posts\/102\/revisions"}],"predecessor-version":[{"id":10540,"href":"https:\/\/www.mrericsir.com\/blog\/wp-json\/wp\/v2\/posts\/102\/revisions\/10540"}],"wp:attachment":[{"href":"https:\/\/www.mrericsir.com\/blog\/wp-json\/wp\/v2\/media?parent=102"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mrericsir.com\/blog\/wp-json\/wp\/v2\/categories?post=102"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mrericsir.com\/blog\/wp-json\/wp\/v2\/tags?post=102"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}