   Trying to understand...
  I am working on my first real game with graphics.  I want to create a tetris like clone with a few of my own twists.  I could just push forward with some global variables or something like that, but I would like it to be professional and have spent some time researching how to use dynamically created vectors like a two dimensional array.  I found this link: http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.19 But I don't understand exactly how it works.#include <vector>template<typename T>  // See section on templates for moreclass Matrix {public:Matrix(unsigned nrows, unsigned ncols);// Throws a BadSize object if either size is zeroclass BadSize { };// No need for any of The Big Three!// Access methods to get the (i,j) element:T&  operator() (unsigned i, unsigned j);   //subscript operators often come in pairsT const& operator() (unsigned i, unsigned j) const;  // subscript operators often come in pairs// These throw a BoundsViolation object if i or j is too bigclass BoundsViolation { };unsigned nrows() const;  // #rows in this matrixunsigned ncols() const;  // #columns in this matrixprivate:std::vector<std::vector<T> > data_;};template<typename T>inline unsigned Matrix<T>::nrows() const{return data_.size();}template<typename T>inline unsigned Matrix<T>::ncols() const{ return data_[0].size();}template<typename T>inline T& Matrix<T>::operator() (unsigned row, unsigned col){if(row >= nrows() || col >= ncols())throw BoundsViolation();return data_[row][col];}template<typename T>inline T const& Matrix<T>::operator() (unsigned row, unsigned col) const{if (row >= nrows() || col >= ncols())throw BoundsViolation();return data_[row][col];}template<typename T>Matrix<T>::Matrix(unsigned nrows, unsigned ncols) : data_ (nrows){if (nrows == 0 || ncols == 0)throw BadSize();for (unsigned i = 0; i < nrows; ++i)data_.resize(ncols);}Does "inline T& Matrix<T>::operator() (unsigned row, unsigned col)" allow me to set values in the 2d vector array?What exactly is this constructor doing?  The part I'm really thrown by is: data_ (nrows)What exactly is being implemented?  Thanks for your help.   
Quote:Does "inline T& Matrix<T>::operator() (unsigned row, unsigned col)" allow me to set values in the 2d vector array?Yes. It returns a (non-constant) reference to the specified element, though which the element can be modified.Quote:What exactly is this constructor doing?  The part I'm really thrown by is: data_ (nrows)What exactly is being implemented?The part after the : is an initializer list (which you may already know). The vector constructor in question takes the number of elements as its argument, so the above bit of code initializes the vector with nrows elements.The array initialization could actually be written a little more concisely as:data_(nrows, std::vector<T>(ncols))Eliminating the need for the loop in the constructor body. (It would be also be a good idea to typedef std::vector<T>.)Note that the method shown here isn't really the recommended method for managing multi-dimensional array data in C++. Using a single array to store the data and indexing via simple arithmetic has some (possibly slight) advantages, including (potentially) less fragmentation and better cache coherency.I am also obligated to mention boost::multi_array, which is well-tested and does exactly what you're wanting. However, writing a multi-dimensional array class from scratch is a good exercise and is definitely not a bad idea. (For production code though, I'd recommend using multi_array.)   ;  the part that "really throws" you is called an initialiser list, generally if you have some member variables that you want initialised upon construction of the object you would place the colon and list off all the variables you want initlised, WITH parentheses mind you, dont try and use the assignment operator.for example, I have a class 'Pie' with two member varibles; mFlavour, mSlicesLeft:enum PieFlavourEnum {Apple,Berry,Pecan,Cherry,Pumpkin,};class Pie{public:Pie(PieFlavourEnum);PieFlavourEnum mFlavour;unsigned int mSlicesLeft;};Pie::Pie(PieFlavourEnum flav) : mFlavour(flav), mSlicesLeft(8){}// bleh stupid code...Here we can see that I begin the initliser list with a colon after the last bracket of the constructor and list of each member seperating them all with a comma.. easy eh?EDIT: To slow!... ><   ;  I appreciate your response jyk.  I will probably change my code to use the single dimensional array while continuing to work with the multiple dimensional vector as a data structures exercise.  What better way to ensure that I understand what is going on.  I'm curious why you suggest doing a typedef std::vector<T>?Thanks for the explanation CodeCriminal.  That additional detail proved quite useful in sparking my memory.  It has been some time since I've dealt with an initialiser list.   ;Quote:I'm curious why you suggest doing a typedef std::vector<T>?In this context it's mostly for code clarity.I suppose some might argue that std::vector<T> is *more* clear because you don't have to track down the typedef definition to see what the type actually is (if you need to know the actual type for some reason, that is).However, template syntax in C++ can quickly become extremely unwieldy without the use of typedefs. Once you get into using iterators, multiple template arguments, and various other template features, typedefs can easily make the difference between a short, concise, and easy-to-read expression, and a lengthy, somewhat impenetrable expression. As you continue to explore template programming you're bound to encounter some of these situations, and then you'll see how and why typedef's can be useful :)Typedefs also provide a measure of abstraction. This isn't so relevant in this case (since a vector is arguably the most logical choice here), but in many cases the actual type used isn't that important and really doesn't need to be cluttering up the code. In other cases, it's beneficial to be able to change a type easily without having to make multiple modifications to your code.As an example, if you were to typedef std::vector<T> as, say, data_t, you could then change the data storage type by changing one line of code rather than having to modify the code everywhere std::vector<T> appears. (Again, it could be argued that the container type used in a multi-dimensional array class is unlikely to change. Even then though, you might decide to use a custom allocator, or even replace vector with a custom dynamic array class for some reason or other, and in these cases you'd probably be glad you used a typedef.)   ;Quote:Original post by jykQuote:I'm curious why you suggest doing a typedef std::vector<T>?However, template syntax in C++ can quickly become extremely unwieldy without the use of typedefs. Once you get into using iterators, multiple template arguments, and various other template features, typedefs can easily make the difference between a short, concise, and easy-to-read expression, and a lengthy, somewhat impenetrable expression. As you continue to explore template programming you're bound to encounter some of these situations, and then you'll see how and why typedef's can be useful :)auto somewhat alleviates this problem, if you've got access to it :)   ;Quote:auto somewhat alleviates this problem, if you've got access to it :)Yes, absolutely. (Looking forward to upgrading to VC++ 2010 for this very reason :)   ;  Thank you for your responses.  They have been insightful and very helpful. I'll try and post on my progress.   