How do you define 2D arrays using New Operator?

D

Dennis

I would like to dynamically allocate in a sub a 2 dimensional Array

float *myarray = new float [n][n];

of course I get an error. How do you allocate a 2D array using the New
operator?

I currently use

static float gxy[10000][10000];

but I don't want my array in the sub to use up my stack space.

Also does the New operator automatically make the values in the array static if
the array pointer is never deleted when the sub is ended? That is I only
allocate the array once the first time I enter the sub. All subsequent sub
calls skip the array allocation section and use the array pointer that was
allocated in the first sub call. The pointer and values in the array are not
touched when the sub ends?

Thanks for any help.

Dennis
 
M

Mike Wahler

I would like to dynamically allocate in a sub a 2 dimensional Array

float *myarray = new float [n][n];

of course I get an error. How do you allocate a 2D array using the New
operator?
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.15

I currently use

static float gxy[10000][10000];

but I don't want my array in the sub to use up my stack space.

Also does the New operator automatically make the values in the array static if
the array pointer is never deleted when the sub is ended?

No. An object can have one of three 'storage durations':
automatic, static, or allocated. 'new' allocates an object,
and the object 'lives' until specifically deallocated with
'delete', or the program terminates.
That is I only
allocate the array once the first time I enter the sub. All subsequent sub
calls skip the array allocation section and use the array pointer that was
allocated in the first sub call. The pointer and values in the array are not
touched when the sub ends?

See above.

-Mike
 
D

Daniel T.

I would like to dynamically allocate in a sub a 2 dimensional Array

float *myarray = new float [n][n];

of course I get an error. How do you allocate a 2D array using the New
operator?

Use a class:
========== ========== ========== ========== ========== ==========

template < typename T, typename U = std::deque< T > >
class Matrix {
public:
typedef typename U::size_type size_type;
typedef typename U::reference reference;
typedef typename U::const_reference const_reference;
typedef typename U::iterator iterator;
typedef typename U::const_iterator const_iterator;

Matrix(): h_limit( 0 ), v_limit( 0 ) { }
Matrix( size_type h, size_type v ): buffer( h * v ), h_limit( h ),
v_limit( v ) { }

reference operator()( size_type h, size_type v ) {
check_limits( h, v );
return buffer[h_limit * h + v];
}

const_reference operator()( size_type h, size_type v ) const {
check_limits( h, v );
return buffer[h_limit * h + v];
}

iterator begin() { return buffer.begin(); }
iterator end() { return buffer.end(); }
const_iterator begin() const { return buffer.begin(); }
const_iterator end() const { return buffer.end(); }


private:
void check_limits( size_type h, size_type v ) const {
if ( h >= h_limit || v >= v_limit ) throw std::eek:ut_of_range(
"Matrix" );
}
U buffer;
size_type h_limit, v_limit;
};
========== ========== ========== ========== ========== ==========

To use the above simply:

Matrix<float> gxy( 10000, 10000 );
float value = gxy( 234, 543 );
assert( value == 0 );
 
D

Derrick Coetzee

I would like to dynamically allocate in a sub a 2 dimensional Array

One way to do this, although not as safe or efficient as using a class,
is to allocate an array of arrays:

template <typename T>
T** new2D(int numRows, int numCols) {
T** a = new T*[numRows];
for(int i=0; i<numRows; i++) {
a = new T[numCols];
}
}

You then index it like this:
a[row][col]
 
D

Dennis

Thanks Daniel.

Your example teaches me a lot about classes.

I've some work to do to understand it completely !

Dennis

Daniel T. said:
I would like to dynamically allocate in a sub a 2 dimensional Array

float *myarray = new float [n][n];

of course I get an error. How do you allocate a 2D array using the New
operator?

Use a class:
========== ========== ========== ========== ========== ==========

template < typename T, typename U = std::deque< T > >
class Matrix {
public:
typedef typename U::size_type size_type;
typedef typename U::reference reference;
typedef typename U::const_reference const_reference;
typedef typename U::iterator iterator;
typedef typename U::const_iterator const_iterator;

Matrix(): h_limit( 0 ), v_limit( 0 ) { }
Matrix( size_type h, size_type v ): buffer( h * v ), h_limit( h ),
v_limit( v ) { }

reference operator()( size_type h, size_type v ) {
check_limits( h, v );
return buffer[h_limit * h + v];
}

const_reference operator()( size_type h, size_type v ) const {
check_limits( h, v );
return buffer[h_limit * h + v];
}

iterator begin() { return buffer.begin(); }
iterator end() { return buffer.end(); }
const_iterator begin() const { return buffer.begin(); }
const_iterator end() const { return buffer.end(); }


private:
void check_limits( size_type h, size_type v ) const {
if ( h >= h_limit || v >= v_limit ) throw std::eek:ut_of_range(
"Matrix" );
}
U buffer;
size_type h_limit, v_limit;
};
========== ========== ========== ========== ========== ==========

To use the above simply:

Matrix<float> gxy( 10000, 10000 );
float value = gxy( 234, 543 );
assert( value == 0 );
 
R

red floyd

Derrick said:
I would like to dynamically allocate in a sub a 2 dimensional Array


One way to do this, although not as safe or efficient as using a class,
is to allocate an array of arrays:

template <typename T>
T** new2D(int numRows, int numCols) {
T** a = new T*[numRows];
for(int i=0; i<numRows; i++) {
a = new T[numCols];
}
}

You then index it like this:
a[row][col]


But the data in the 2D vector isn't contiguous.

template <typename T>
T** new2D(int rows, int cols))
{
T* v = new T[rows * cols];
T** p = new T*[rows];
for (int j = 0 ; j < rows; ++j)
p[j] = v + (j * cols);
return p;
}

Still accessed the same way, and deletion is easier:

delete[] &v[0][0];
delete[] v;
 
D

Dennis

Thanks Derrick,

Interesting solution to the 2D problem using pointers.

If I put this into a DLL sub and I don't delete it. When the Dll is unloaded
will the storage of the 2d array be free'd?

Dennis

Derrick Coetzee said:
I would like to dynamically allocate in a sub a 2 dimensional Array

One way to do this, although not as safe or efficient as using a class,
is to allocate an array of arrays:

template <typename T>
T** new2D(int numRows, int numCols) {
T** a = new T*[numRows];
for(int i=0; i<numRows; i++) {
a = new T[numCols];
}
}

You then index it like this:
a[row][col]
 
D

Dennis

Hi Mike,

Thanks for the URL.

One way to dynamically allocate a 1D array in a sub and not have to make it
global so that you can use the array values on the next entry into the sub is:

float MySub(int N){
.....
static float *myarray;
static long lEntry=0;
.....
lEntry++;
if lEntry==1 { myarray = new float [N]; }


Mike Wahler said:
I would like to dynamically allocate in a sub a 2 dimensional Array

float *myarray = new float [n][n];

of course I get an error. How do you allocate a 2D array using the New
operator?
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.15

I currently use

static float gxy[10000][10000];

but I don't want my array in the sub to use up my stack space.

Also does the New operator automatically make the values in the array static if
the array pointer is never deleted when the sub is ended?

No. An object can have one of three 'storage durations':
automatic, static, or allocated. 'new' allocates an object,
and the object 'lives' until specifically deallocated with
'delete', or the program terminates.
That is I only
allocate the array once the first time I enter the sub. All subsequent sub
calls skip the array allocation section and use the array pointer that was
allocated in the first sub call. The pointer and values in the array are not
touched when the sub ends?

See above.

-Mike
 
M

Mike Wahler

Thanks Derrick,

Interesting solution to the 2D problem using pointers.

If I put this into a DLL sub and I don't delete it. When the Dll is unloaded
will the storage of the 2d array be free'd?

That depends upon your implementation and platform, the language
does not specify. I wouldn't depend upon it. I advise the 'rule
of thumb': if you allocate it, deallocate it when you're done with
it. Then nothing is left to chance.

BTW please don't top-post.


-Mike
 
D

Dennis

Mike Wahler said:
That depends upon your implementation and platform, the language
does not specify. I wouldn't depend upon it. I advise the 'rule
of thumb': if you allocate it, deallocate it when you're done with
it. Then nothing is left to chance.

BTW please don't top-post.


-Mike
Mike,

Deallocating the array is the problem. Another App, which I have not control
over, loads my DLL and calls the subs 10000's of times. I have no way of knowing
when the App has finished with my DLL until it unloads it. I don't want to use
stack space, I need to save the values in the array between calls, and I don't
know what the initial array memory requirements are going to be until the first
call of the sub. I know if I set up global arrays then the mem is freed upon
unloading. But global arrays are not dynamic and must be fixed. So the static
*myarray solution was proposed.
 
M

Mike Wahler

Mike,

Deallocating the array is the problem. Another App, which I have not control
over, loads my DLL and calls the subs 10000's of times. I have no way of knowing
when the App has finished with my DLL until it unloads it. I don't want to use
stack space, I need to save the values in the array between calls, and I don't
know what the initial array memory requirements are going to be until the first
call of the sub. I know if I set up global arrays then the mem is freed upon
unloading. But global arrays are not dynamic and must be fixed. So the static
*myarray solution was proposed.

Well, I'm far from a 'DLL expert', so I won't attempt to advise you
about that. But I suggest you take this issue to
comp.os.ms-windows.programmer.win32, where the Win32 experts
hang out.

-Mike
 
D

Daniel T.

Thanks Daniel.

Your example teaches me a lot about classes.

I've some work to do to understand it completely !

Let me present a simpler class that does the same thing, but isn't as
flexable:

template < typename T >
class Matrix {
void check_limits( size_type h, size_type v ) const {
if ( h >= h_limit || v >= v_limit )
throw std::eek:ut_of_range( "Matrix" );
}
std::deque<T> buffer;
unsigned h_limit, v_limit;
public:
Matrix():
h_limit( 0 ),
v_limit( 0 ) { }
Matrix( unsigned h, unsigned v ):
buffer( h * v ),
h_limit( h ),
v_limit( v ) { }
T& cell_at( unsigned h, unsigned v ) {
check_limits();
return buffer[ h_limit * h + v ];
}
const T& cell_at( unsigned h, unsigned v ) const {
check_limits();
return buffer[ h_limit * h + v ];
}
};

use it like this:

Matrix<float> m( 100, 100 )
assert( m.cell_at( 12, 5 ) == 0 );
m.cell_at( 12, 5 ) = 9;
assert( m.cell_at( 12, 5 ) == 9 );
Daniel T. said:
I would like to dynamically allocate in a sub a 2 dimensional Array

float *myarray = new float [n][n];

of course I get an error. How do you allocate a 2D array using the New
operator?

Use a class:
========== ========== ========== ========== ========== ==========

template < typename T, typename U = std::deque< T > >
class Matrix {
public:
typedef typename U::size_type size_type;
typedef typename U::reference reference;
typedef typename U::const_reference const_reference;
typedef typename U::iterator iterator;
typedef typename U::const_iterator const_iterator;

Matrix(): h_limit( 0 ), v_limit( 0 ) { }
Matrix( size_type h, size_type v ): buffer( h * v ), h_limit( h ),
v_limit( v ) { }

reference operator()( size_type h, size_type v ) {
check_limits( h, v );
return buffer[h_limit * h + v];
}

const_reference operator()( size_type h, size_type v ) const {
check_limits( h, v );
return buffer[h_limit * h + v];
}

iterator begin() { return buffer.begin(); }
iterator end() { return buffer.end(); }
const_iterator begin() const { return buffer.begin(); }
const_iterator end() const { return buffer.end(); }


private:
void check_limits( size_type h, size_type v ) const {
if ( h >= h_limit || v >= v_limit ) throw std::eek:ut_of_range(
"Matrix" );
}
U buffer;
size_type h_limit, v_limit;
};
========== ========== ========== ========== ========== ==========

To use the above simply:

Matrix<float> gxy( 10000, 10000 );
float value = gxy( 234, 543 );
assert( value == 0 );
 
D

Dennis

Thanks again Daniel.

It looks like I'm going to have to buy and study some of those books recommended
by Mike Tyndell to completely understand these two examples.

Dennis

Daniel T. said:
Thanks Daniel.

Your example teaches me a lot about classes.

I've some work to do to understand it completely !

Let me present a simpler class that does the same thing, but isn't as
flexable:

template < typename T >
class Matrix {
void check_limits( size_type h, size_type v ) const {
if ( h >= h_limit || v >= v_limit )
throw std::eek:ut_of_range( "Matrix" );
}
std::deque<T> buffer;
unsigned h_limit, v_limit;
public:
Matrix():
h_limit( 0 ),
v_limit( 0 ) { }
Matrix( unsigned h, unsigned v ):
buffer( h * v ),
h_limit( h ),
v_limit( v ) { }
T& cell_at( unsigned h, unsigned v ) {
check_limits();
return buffer[ h_limit * h + v ];
}
const T& cell_at( unsigned h, unsigned v ) const {
check_limits();
return buffer[ h_limit * h + v ];
}
};

use it like this:

Matrix<float> m( 100, 100 )
assert( m.cell_at( 12, 5 ) == 0 );
m.cell_at( 12, 5 ) = 9;
assert( m.cell_at( 12, 5 ) == 9 );
Daniel T. said:
I would like to dynamically allocate in a sub a 2 dimensional Array

float *myarray = new float [n][n];

of course I get an error. How do you allocate a 2D array using the New
operator?

Use a class:
========== ========== ========== ========== ========== ==========

template < typename T, typename U = std::deque< T > >
class Matrix {
public:
typedef typename U::size_type size_type;
typedef typename U::reference reference;
typedef typename U::const_reference const_reference;
typedef typename U::iterator iterator;
typedef typename U::const_iterator const_iterator;

Matrix(): h_limit( 0 ), v_limit( 0 ) { }
Matrix( size_type h, size_type v ): buffer( h * v ), h_limit( h ),
v_limit( v ) { }

reference operator()( size_type h, size_type v ) {
check_limits( h, v );
return buffer[h_limit * h + v];
}

const_reference operator()( size_type h, size_type v ) const {
check_limits( h, v );
return buffer[h_limit * h + v];
}

iterator begin() { return buffer.begin(); }
iterator end() { return buffer.end(); }
const_iterator begin() const { return buffer.begin(); }
const_iterator end() const { return buffer.end(); }


private:
void check_limits( size_type h, size_type v ) const {
if ( h >= h_limit || v >= v_limit ) throw std::eek:ut_of_range(
"Matrix" );
}
U buffer;
size_type h_limit, v_limit;
};
========== ========== ========== ========== ========== ==========

To use the above simply:

Matrix<float> gxy( 10000, 10000 );
float value = gxy( 234, 543 );
assert( value == 0 );
 
D

Dennis

Mike Wahler said:
Well, I'm far from a 'DLL expert', so I won't attempt to advise you
about that. But I suggest you take this issue to
comp.os.ms-windows.programmer.win32, where the Win32 experts
hang out.

-Mike
Mike.

This is just what NeilB plus others said (accept Alf P. Steinbach who agreed
with me that this was a C++ lang topic and quoted §3.6.2/3 to prove it) when on
3/14/03 I sent the post entitled "Initialize Global Array in DLL before DLL
Functions are Called?"

Once again you are shifting the burden when you can't answer the question.

Dennis
 
A

Alf P. Steinbach

* (e-mail address removed):
* Mike Wahler:

This is just what NeilB plus others said (accept Alf P. Steinbach who agreed
with me that this was a C++ lang topic and quoted §3.6.2/3 to prove it) when on
3/14/03 I sent the post entitled "Initialize Global Array in DLL before DLL
Functions are Called?"

I take it you're referring to <url:
http://groups.google.com/[email protected]>.

The question above is a bit different but §3.6.2/3 (assuming you've quoted
that paragraph identifier correctly) still applies for the creation part.

Namely, you can use a static smart-pointer object, which is guaranteed
to be initialized before the first call of a DLL function, and you simply
store a pointer to a suitable array in that smart-pointer on first call
of your "sub" (by the way, such things are called "functions" in C++).

Regarding guaranteed call of that smart-pointer's destructor on "unloading"
of the DLL, well, I'm too lazy to check it out, but I have a suspicion that
it isn't guaranteed by the C++ standard since there's no such thing as
"unloading" of code in C++ -- and so regarding that aspect I agree with
Mike that you're probably better served by asking in a Windows or
compiler-specific group (the group Mike mentioned is a good Windows one).

Somebody check the standard... ?
 
D

Dennis

* (e-mail address removed):
Regarding guaranteed call of that smart-pointer's destructor on "unloading"
of the DLL, well, I'm too lazy to check it out, but I have a suspicion that
it isn't guaranteed by the C++ standard since there's no such thing as
"unloading" of code in C++ -- and so regarding that aspect I agree with
Mike that you're probably better served by asking in a Windows or
compiler-specific group (the group Mike mentioned is a good Windows one).
Pushing this query to comp.os.ms-windows.programmer.win32 escapes a C++ Lang
question that is used everyday in c++ programs in the financial community.

For instance suppose you have an algorithm that needs the last 10,000 prices of
a process that's delivering 200 prices a second. The algo runs all day and the
program is closed at the end of the day. The main routine calls a function in
another users DLL at every new price. In that DLL the memory required to save
the last "x" prices is variable and defined by the first call to the function in
that DLL. The user might want to calculate the function on the last 1000 or
50000 or maybe 100,000 prices on each call to the function on every tick. The
Main calls the function on each new price. The 10,000 prices are updated by
deleting the first price and moving the 9999 prices back 1 space and adding the
latest price to the end(a circular array) and a new calculation is done and
passed to the Main. The function has to dynamical allocate static memory on the
heap. Global memory requires fixed storage and is not dynamic. Thus if the
Static float *myarray .....myarray=new float[N] is used inside the function as
in my previous example I think it is the balleywick of the C++ lang to define
whether or not the memory is freed when the DLL is unloaded by main without a
delete[] in the function.
 
A

Alf P. Steinbach

* (e-mail address removed):
Pushing this query to comp.os.ms-windows.programmer.win32 escapes a C++ Lang
question that is used everyday in c++ programs in the financial community.

I doubt that.

For instance suppose you have an algorithm that needs the last 10,000 prices of
a process that's delivering 200 prices a second. The algo runs all day and the
program is closed at the end of the day. The main routine calls a function in
another users DLL at every new price. In that DLL the memory required to save
the last "x" prices is variable and defined by the first call to the function in
that DLL. The user might want to calculate the function on the last 1000 or
50000 or maybe 100,000 prices on each call to the function on every tick. The
Main calls the function on each new price. The 10,000 prices are updated by
deleting the first price and moving the 9999 prices back 1 space and adding the
latest price to the end(a circular array) and a new calculation is done and
passed to the Main. The function has to dynamical allocate static memory on the
heap. Global memory requires fixed storage and is not dynamic. Thus if the
Static float *myarray .....myarray=new float[N] is used inside the function as
in my previous example I think it is the balleywick of the C++ lang to define
whether or not the memory is freed when the DLL is unloaded by main without a
delete[] in the function.

Not sure what you mean, but if the DLL is not dynamically unloaded then
there is no problem (you have ordinary C++ rules of destruction in opposite
order of construction, and a std::vector will do), and if it is dynamically
unloaded then you can either go the OS/compiler-specific route (ask about
that in an appropriate newsgroup), or you can inflict some design on the
code, e.g. giving client code responsibility for allocation & deallocation.
 
D

Daniel T.

Daniel T. said:
Thanks Daniel.

Your example teaches me a lot about classes.

I've some work to do to understand it completely !

Let me present a simpler class that does the same thing, but isn't as
flexable:

template < typename T >
class Matrix {
void check_limits( unsigned h, unsigned v ) const {
if ( h >= h_limit || v >= v_limit )
throw std::eek:ut_of_range( "Matrix" );
}
std::deque<T> buffer;
unsigned h_limit, v_limit;
public:
Matrix():
h_limit( 0 ),
v_limit( 0 ) { }
Matrix( unsigned h, unsigned v ):
buffer( h * v ),
h_limit( h ),
v_limit( v ) { }
T& cell_at( unsigned h, unsigned v ) {
check_limits();
return buffer[ h_limit * h + v ];
}
const T& cell_at( unsigned h, unsigned v ) const {
check_limits();
return buffer[ h_limit * h + v ];
}
};

use it like this:

Matrix<float> m( 100, 100 )
assert( m.cell_at( 12, 5 ) == 0 );
m.cell_at( 12, 5 ) = 9;
assert( m.cell_at( 12, 5 ) == 9 );
Thanks again Daniel.

It looks like I'm going to have to buy and study some of those books
recommended
by Mike Tyndell to completely understand these two examples.

Which method(s) are you having trouble understanding?

check_limits(unsigned h, unsigned v): checks to make sure that h & v
represent a cell in the Matrix.

Matrix(): creates an empty (0 x 0) matrix.

Matrix(unsigned h, unsigned v): creates and initializes all the elements
in an h x v matrix.

cell_at(unsigned h, unsigned v): returns a modifiable reference to a
cell in the matrix.

cell_at(unsigned h, unsigned v) const: returns an unmodifiable reference
to a cell in the matrix.

The matrix is actually held in an array (a deque in this case, but it
could as easily be held in a vector.) Something like this:

00 10 20
01 11 21
02 12 22

is held in the array like this:

00 10 20 01 11 21 02 12 22

Get it now?
 
D

Dennis

template said:
class Matrix {
void check_limits( unsigned h, unsigned v ) const {
if ( h >= h_limit || v >= v_limit )
throw std::eek:ut_of_range( "Matrix" );
}
std::deque<T> buffer;
unsigned h_limit, v_limit;
public:
Matrix():
h_limit( 0 ),
v_limit( 0 ) { }
Matrix( unsigned h, unsigned v ):
buffer( h * v ),
h_limit( h ),
v_limit( v ) { }
T& cell_at( unsigned h, unsigned v ) {
check_limits();
return buffer[ h_limit * h + v ];
}
const T& cell_at( unsigned h, unsigned v ) const {
check_limits();
return buffer[ h_limit * h + v ];
}
};
use it like this:

Matrix<float> m( 100, 100 )
assert( m.cell_at( 12, 5 ) == 0 );
m.cell_at( 12, 5 ) = 9;
assert( m.cell_at( 12, 5 ) == 9 );

Which method(s) are you having trouble understanding?

check_limits(unsigned h, unsigned v): checks to make sure that h & v
represent a cell in the Matrix.

Matrix(): creates an empty (0 x 0) matrix.

Matrix(unsigned h, unsigned v): creates and initializes all the elements
in an h x v matrix.

cell_at(unsigned h, unsigned v): returns a modifiable reference to a
cell in the matrix.

cell_at(unsigned h, unsigned v) const: returns an unmodifiable reference
to a cell in the matrix.

The matrix is actually held in an array (a deque in this case, but it
could as easily be held in a vector.) Something like this:

00 10 20
01 11 21
02 12 22

is held in the array like this:

00 10 20 01 11 21 02 12 22
Thanks again for your explanation.

I'm having trouble understanding:

Where does the function "cell_at" come from.

I'm not to familiar with the use of "std::deque<T> buffer;" where are some good
examples? I checked the help section of vc++6.0 but the deque examples were not
the same.

Why do h and v have to be unsigned?

Why is the "const {" there in
"void check_limits( unsigned h, unsigned v ) const{"
const T& cell_at( unsigned h, unsigned v ) const {

If the class is defined outside the function is "buffer" static when the
function is exited?

Thanks for your time and help in understanding this Class.

Dennis
 
M

Mike Wahler

template < typename T >
class Matrix {
void check_limits( unsigned h, unsigned v ) const {
if ( h >= h_limit || v >= v_limit )
throw std::eek:ut_of_range( "Matrix" );
}
std::deque<T> buffer;
unsigned h_limit, v_limit;
public:
Matrix():
h_limit( 0 ),
v_limit( 0 ) { }
Matrix( unsigned h, unsigned v ):
buffer( h * v ),
h_limit( h ),
v_limit( v ) { }
T& cell_at( unsigned h, unsigned v ) {
check_limits();
return buffer[ h_limit * h + v ];
}
const T& cell_at( unsigned h, unsigned v ) const {
check_limits();
return buffer[ h_limit * h + v ];
}
};
use it like this:

Matrix<float> m( 100, 100 )
assert( m.cell_at( 12, 5 ) == 0 );
m.cell_at( 12, 5 ) = 9;
assert( m.cell_at( 12, 5 ) == 9 );

Which method(s) are you having trouble understanding?

check_limits(unsigned h, unsigned v): checks to make sure that h & v
represent a cell in the Matrix.

Matrix(): creates an empty (0 x 0) matrix.

Matrix(unsigned h, unsigned v): creates and initializes all the elements
in an h x v matrix.

cell_at(unsigned h, unsigned v): returns a modifiable reference to a
cell in the matrix.

cell_at(unsigned h, unsigned v) const: returns an unmodifiable reference
to a cell in the matrix.

The matrix is actually held in an array (a deque in this case, but it
could as easily be held in a vector.) Something like this:

00 10 20
01 11 21
02 12 22

is held in the array like this:

00 10 20 01 11 21 02 12 22
Thanks again for your explanation.

I'm having trouble understanding:

Where does the function "cell_at" come from.

It came from Daniel, he wrote it. I suspect he used
the name 'cell_at' to mimic the name of a similar
member function from the standard class 'std::vector'.
The vector class has a subscript operator ( [] ) that
works just like with an array, but also like an array
is not bounds checked. It also has a element-access
function which does do bounds checking, called 'at()'.
So he came up with 'cell_at()' for the name.
I'm not to familiar with the use of "std::deque<T> buffer;"

'std::queue' is one of several 'container' classes provided
by the C++ standard library. It's a templated class (as
are all the containers), with the template parameter 'T'
specifying the actual type of the elements stored in it.

e.g.

where are some good
examples?

I don't know of any online, but a good textbook should have some.
The most recommended book on the standard library is:
www.josuttis.com/libbook I *highly* recommend it.
I checked the help section of vc++6.0 but the deque examples were not
the same.

Why do h and v have to be unsigned?

They don't *have* to be, but it makes sense for them to be.
A signed type would allow for negative values (and only has
half the value range of the corresponding unsigned type).
But what would a negative size or index *mean*? Also note that
'h' and 'v' shouldn't really be just any unsigned type, but type
'size_t', which is an (implementation-defined) unsigned type which
is guaranteed to be able to hold the largest possible sized object
(or the largest number of one-byte objects). Actually it should
have the same type as the container class ('deque' in this case)'s
'size_type' type. But I suppose allowing for that would make the
code even harder for you to follow. :)
Why is the "const {" there in
"void check_limits( unsigned h, unsigned v ) const{"
const T& cell_at( unsigned h, unsigned v ) const {

Look up 'const member function'. The 'const' after the
parameter list is a 'promise' to the compiler that the
function will not modify the object for which it was called.
If you write code that tries to do so, you'll get a compile
error.
If the class is defined outside the function

The class is defined outside any function (as it should be).
is "buffer" static when the
function is exited?

What function? Anyway, an object will have static storage duration
in two cases:

1. It's defined at file scope (outside any function or class)
2. It's specifically qualified with the 'static' keyword.

-Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top