Overloading subscript operator and working with double-pointers? - c++

I have the following variable that I need to work with, and have to write my own wrapper around it for an assignment. I am going beyond the assignment (since I am going to have to use this wrapper I make) and wanting to overload the subscript operator in my wrapper in order to use it with the double pointer array. What I mean in code is this:
What I have:
From given header for library:
typedef struct { // A pixel stores 3 bytes of data:
byte red; // intensity of the red component
byte green; // intensity of the green component
byte blue; // intensity of the blue component
} pixel;
typedef struct {
int rows, cols; /* pic size */
pixel **pixels; /* image data */
} image;
My class (of course included in header):
pixels& MyWrapper::operator[] (const int nIndex) {
return Image.pixels[nIndex]; // where Image is of type image
}
Of course this won't work since the double pointer returns a pointer, which is not what I'm telling it to return, yet returning *pixels& doesn't return it either. Just to sate my curiosity and to help me understand why this isn't possible, could someone tell me how this would be implemented if it can be at all, and why it is that way? Keep in mind I don't understand pointers very well yet (I know of the basics of how they work, but thats it), and am hoping to use this to very much broaden my understanding.

this is more typical, for c++:
#include <vector>
namespace AA {
class t_point {
public:
t_point(const size_t& X, const size_t& Y) : d_x(X), d_y(Y) {
}
const size_t& x() const { return this->d_x; }
const size_t& y() const { return this->d_y; }
private:
size_t d_x;
size_t d_y;
};
class t_array {
public:
// abusive, but possible. prefer `at`
const int& operator[](const t_point& idx) const {
return this->at(idx.x(), idx.y());
}
const int& at(const t_point& idx) const {
return this->at(idx.x(), idx.y());
}
const int& at(const size_t& x, const size_t& y) const {
return this->d_objects[x][y];
}
private:
// or use your c image representation...
std::vector<std::vector<int> > d_objects;
private:
static const int& ctest(const t_array& arr) {
const t_point pt(1, 2);
return arr[pt];
return arr.at(pt);
return arr.at(pt.d_x, pt.d_y);
}
};
}
the big problem with using one index in this case it that it is not clear which index (pixel) you are attempting to access, while pushing all the coordinate calculations off to the client. if it's a single pointer, you'd still push the problem onto the client, but you'd be able access the index predictably.
with double... the layout in memory can vary, it is not necessarily contiguous. it's just a bad design to publish it as a single value (logically, as a 1D array), rather than a 2D array or a point (for example).

It's not clear why you are using double indirection in the first place.
If pixels is a double pointer to an array of pixels, you can do
pixels& MyWrapper::operator[] (const int nIndex) {
return (*Image.pixels)[nIndex]; // where Image is of type image
}
If pixels is a pointer to an array of pointers to arrays, then you need two indices:
pixels& MyWrapper::operator() ( int xIndex, int yIndex ) {
return Image.pixels[yIndex][xIndex]; // where Image is of type image
}
There are a few weird things going on here.
typedef class { } identifier is not good C++. Use class identifier { };, or else the class has no name, so you cannot define member functions outside the class { } scope. (Among other problems.)
There is no reason to make a parameter type const int. Plain int accomplishes the same thing.
There is no apparent reason for the double indirection. Typically in C++ we avoid the direct use of pointers. There is probably a prepackaged standard structure you can use instead.

Use boost::multi_array

Related

C++ Accessing and Manipulating 2D Pointer Array from within get function

I am making a battleships game for my coursework, and I have run into some problems with the get functions in one of the classes I am using. The basic idea of my game is to create a 2D 10X10 array, called grid, filled with null pointers to represent the board. I have created 2 classes, Board and Ship. The grid array is of type Ship, and I use an algorithm to fill the array with Ships randomly. I use the Board class to access the grid array and the hits array (which I use to track hits).
However I cannot figure out how the getShips function can return the grid array. The hits array is just booleans so that was easy enough, but I am not proficient enough at C++ to make the getShips function properly return the grid array, which is a Ship pointer type. I would greatly appreciate any help.
class Board
{
private:
Ship *grid[10][10];
bool hits[10][10];
public:
// get functions
Ship *getShips()
{
return grid;
}
bool getHits()
{
return hits;
}
};
I was also wondering if it would be possible to manipulate the array in other functions by calling the getShips function. Something like:
for (int x=0; x<10; x++)
{
for (int y=0; y<10; y++)
{
board.getShips()[x][y]=nullptr;
}
}
Ok. First I would modify the getShips and getHits functions. To have something like that :
Ship *getShips(int x, int y){ return grid[x+y*10]; }
bool getHits(int x, int y){return hits[x+y*10];}
That way you'll simplify your code and avoid some errors.
When you declare a multidimensional array like you do with
Ship *grid[10][10];
bool hits[10][10];
you're basically declaring pointers to pointers to pointers to ships.
I would try to use a minimum amount of pointers if you're writing in C++. Try to use the stl containers instead. They do automatic memory management for you which may save you some time down the road.
I suggest to change your interface to something like:
class Board
{
private:
Ship *grid[10][10];
bool hits[10][10];
public:
Ship* getShip(int x, int y) const { return grid[x][y]; }
Ship*& getShip(int x, int y) { return grid[x][y]; }
bool getHit(int x, int y) const { return hits[x][y]; }
bool& getHit(int x, int y) { return hits[x][y]; }
};
If you really want to return grid and hits, I recommend to use std::array<std::array<Ship*, 10>, 10> grid; (require C++11) instead of Ship *grid[10][10];.
if C++11 is not possible turn back to std::vector.
and then
private:
std::array<std::array<Ship*, 10>, 10> grid;
public:
const std::array<std::array<Ship*, 10>, 10>& getShips() const { return grid; }
std::array<std::array<Ship*, 10>, 10>& getShips() { return grid; }
Currently, it looks like getShips is returning the entire 10x10 array of Ship*-- you need to change what the getShips function is returning:
Ship*** getShips() { ...
However, I would recommend against mixing pointers and arrays. Pointers can be tricksy, and combining with arrays can get very difficult to debug. Instead, you could use all pointers: Ship ***grid; and initialize with new (I'll leave the initialization as an exercise, but here's a site that has an example: http://pleasemakeanote.blogspot.com/2010/07/2d-arrays-in-c-using-new.html).
In reality, it might be better for the Ship class to store the indices of where it exists, perhaps something like this:
class Ship
{
public:
<<member func>>
private:
int nspaces_;
int start_[2];
int end_[2];
}
where you store the beginning index and the final index where the ship is found. You'll need to handle the code to identify the spaces between, but that is trivial. This setup would allow you to replace Ship *grid[10][10] with a single array of Ships.
The getShips function would then become:
...
Ship ships_[<<number of ships>>];
Ship *getShips()
{
return ships_;
}
...
and would be used:
board.getShips()[x][y]
Or...you could add a getShip(int x, int y) method.

C++ Return temporary values and objects that cannot be copied

I know that references can extend the lifetime of a return value in C++. With this phylosophy, I tried the following: I have three clases, 'tensor', 'view' and 'mutable_view'. Operator () on a tensor returns a "const view" object. This view has a private copy constructor so that the view cannot be copied, as it keeps information about the tensor that might not survive beyond the current statement.
#include <iostream>
#include <algorithm>
struct tensor {
int data[10];
class view {
const int *const data;
view();
view(const view &);
public:
view(const int *new_data) : data(new_data) {}
int operator*() const { return *data; }
};
class mutable_view {
int *const data;
mutable_view();
mutable_view(const mutable_view &);
public:
mutable_view(int *new_data) : data(new_data) {}
void operator=(const view &v) {
*data = *v;
}
};
tensor(int n) {
std::fill(data, data+10, n);
}
const view operator()(int ndx) const {
return view(data + ndx);
}
mutable_view at(int ndx) {
return mutable_view(data + ndx);
}
};
int main()
{
tensor a(1);
tensor b(2);
b.at(2) = a(2);
for (int i = 0; i < 10; i++)
std::cout << "a[i] = " << b.data[i] << std::endl;
for (int i = 0; i < 10; i++)
std::cout << "b[i] = " << b.data[i] << std::endl;
exit(0);
}
The problem is that, while this code works in gcc (depends on the version), icc signals a warning and open64 simply does not build it: it demands that the constructors from 'view' be public. Reading icc's message the idea seems to be that the right hand value could be potentially copied by the compiler and thus constructors are needed.
Is this really true? Is there a workaround that preserves the syntax I want to build? By the way they are built, and in order to avoid inefficient implementations based on shared_ptr or other stuff, I need to keep the 'view' objects un-copiable.
Edit 1:
tensor cannot control the lifetime of the views. The views are created by the accessors and their lifetime is limited to the statement where they are used, for the following reasons:
These views are only used for two things: (i) copying data, (ii) extracting portions of the tensor.
The tensors are multidimensional arrays that implement copy-on-write semantics, which means that the views cannot be long-lived objects: if the data changes, they expire.
Edit 2:
Changed the pseudocode description (guys, if you see '...' do you expect it to be compilable?) with one that builds on 'icc' and does not on clang/open64
Go ahead and let the default copy constructors be public. And document that a view or mutable_view is "invalidated" when its tensor is changed or destroyed.
This parallels how the Standard Library deals with iterators, pointers, and references that have a lifetime which depends on another object.
As others already pointed out you missed () here:
const view operator(int ndx) const;
Anyway this declaration means that return value is copied. If you want to avoid copying just return reference for an object:
const view& operator()(int ndx) const;
As I understand 'tensor' is container of 'views' so it manages there lifetime and its safe to return reference. For the same reason tensor::at should return reference to mutable_view:
mutable_view& at(int ndx);
Another question is about default constructor of 'view' - it looks like 'tensor' has to be a friend of 'view' to be able to create its instances
By the way - prefer using 'size_t' as index type instead of just 'int'
My overall feeling of this code - you are trying to implement kind of domain language. Maybe it's better to focus on concrete calculation task?

Offset and pass vector reference

When using arrays you can do something like
class SomeClass
{
public:
int* LockMember( size_t& numInts );
private:
int* member;
size_t numInts;
};
int* SomeClass::LockMember( size_t& out_numInts )
{
out_numInts = numInts - 1;
return member + 1;
}
To return an array offset by some amount so as to prevent someone from modifying some part of contingeous memory, or, atleast, show some intent that this part of contingeous memory of the object should remain untouched.
Since I use vectors everywhere, I am wondering if there was some way to accomplish the same sort of thing:
class SomeClass
{
public:
std::vector<int> LockMember( void );
private:
std::vector<int> member;
};
std::vector<int> SomeClass::LockMember( void )
{
// somehow make a vector with its beginning iterator pointing to member.begin() + 1
// have a size smaller by one, still the same end iterator. The vector must be
// pointing to the same data as in this class as it needs to be modifiable.
return magicOffsetVector;
}
With the commented part replaced by real code. Any ideas?
If I understand you correctly: You want some memory with two parts: At the beginning you want something that can't be touched, and after that you want something that is open for use by client code.
You could do something along the following code. This will give the client code a copy to play with. This does mean you would have to do a lot of copying, though.
class SomeClass
{
public:
std::vector<int> getMember( void ) const;
void setMember(std::vector<int> newContent);
private:
std::vector<int> member;
size_t magicOffset;
};
// Read restricted part
std::vector<int> SomeClass::getMember( void ) const
{
return vector<int>(member.begin() + magicOffset, member.end());
}
// Assign to restricted part
void SomeClass::setMember(const std::vector<int>& v)
{
std::copy(v.begin(), v.end(), member.begin() + magicOffset);
}
In order to avoid the copying, it is possible that you could allocate memory for two vectors, one for the protected part and one for the unprotected part, and use placement new to put both vectors into that memory, thus ensuring that they are in contiguous memory. And then give the client code more or less free access to the public part of the vector. However, there's still the thing with bookkeeping variables in vector, and basically this would be an awful hack that's just waiting to blow up.
However, if you only need access to the unrestricted part on a per-element basis, you could just do range-checking on the arguments, i.e.:
int getElement(size_t idx)
{
idx += magicOffset;
if (idx > member.size() || idx < 0) throw std::out_of_range("Illegal index");
return member[idx];
}
And then either provide a setElement, or return int&.

Handling Huge Multidimensional Arrays in C++

I'm designing a game in C++ similar to Minecraft that holds an enormous amount of terrain data in memory. In general, I want to store an array in memory that is [5][4][5][50][50][50]. This isn't bad since it amounts to about 100mb of virtual memory since my structure will only be about 8 bytes.
However, I'm having trouble figuring out the best way to handle this. I do want this to be in virtual memory, but obviously not on the stack. And I keep making the mistake some how of creating this array on the stack an causing a stack overflow. What I would like to do is below. This is just code that I threw together to give you an example of what I'm doing, I have code with correct syntax on my machine, I just didn't want to clutter the post.
typedef struct modelBlock
{
// Information about the blocks
} BLOCK;
typedef struct modelGrid
{
bool empty;
BLOCK blocksArray[50][50][50];
} GRID;
class Parent
{
Child* child;
Parent(void);
}
Parent::Parent()
{
Child c;
child = &c;
}
class Child
{
GRID grids[5][4][5];
}
However, every time I do this, I cause a stack overflow (appropriate web site choice right?). I played with using pointer based arrays, but I had a lot of trouble with data being lost outside of its scope.
If anyone could give me some insight on how to get my data to store on the heap instead of the stack, or if I should use some other way of creating my array, I'd really appreciate the help. I'd like to avoid using vectors because of overhead, though I'm not sure how substantial it is.
Use boost::multi_array
If you want to allocate something on the heap, use new.
#include <memory>
class Parent
{
std::auto_ptr<Child> child; // use auto_ptr for dynamically-allocated members
Parent(const Parent&); // You probably don't want to copy this giant thing
public:
Parent();
};
Parent::Parent()
: child(new Child) // initialize members with an initializer list
{
}
Also, avoid mixing C and C++ styles. There's no reason to do
typedef struct blah{ ... } BLAH;
in C++. A struct is just a class with all of the members public by default; just like a class, you can refer to the struct type's name without using the struct tag. There's also no need to specify void for a function that takes no parameters.
boost::multi_array (linked in PigBen's answer) is a good choice over raw arrays.
If you want the class created on the heap, create it with new:
Child * c = new Child;
and then of course delete it, or better still use a smart pointer.
In order to do exactly what you're trying to do you have to declare everything as pointers (and pointers to pointers to pointers to pointers) and then allocate each one individually.
Teh sux!
A better option is to simply allocate the ginormous block in one chunk and use multiple variable along with pointer arithmetic to arrive at the correct location.
Edit: Wasn't paying attention and didn't notice your constructor. That's not only not the way to get your Child allocated on the free-store, it's a great way to create situations eliciting undefined behavior. Your Child will be gone when the constructor is through and the pointer to it will then be invalid. I wonder if you shouldn't run through some basic tutorials before trying to write a game.
Here's something that works and can be built upon without the boost dependency. One downside is it removes use of [][][] style of referencing elements, but it's a small cost and can be added.
template<class T>
class Matrix {
unsigned char* _data;
const size_t _depth;
const size_t _cols;
const size_t _rows;
public:
Matrix(const size_t& depth, const size_t& rows, const size_t& cols):
_depth(depth),
_rows(rows),
_cols(cols) {
_data = new unsigned char [depth * rows * cols * sizeof(T)];
}
~Matrix() {
delete[] _data;
}
T& at(const size_t& depthIndex, const size_t& rowIndex, const size_t& colIndex) const {
return *reinterpret_cast<T*>(_data + ((((depthIndex * _cols + colIndex) * _rows) + rowIndex) * sizeof(T)));
}
const size_t& getDepth() const {
return _depth;
}
const size_t& getRows() const {
return _rows;
}
const size_t& getCols() const {
return _cols;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Matrix<int> block(50, 50, 50);
size_t d, r, c;
for (d = 0; d < block.getDepth(); d++) {
for (r = 0; r < block.getRows(); r++) {
for (c = 0; c < block.getCols(); c++) {
block.at(d, r, c) = d * 10000000 + r * 10000 + c;
}
}
}
for (d = 0; d < block.getDepth(); d++) {
for (r = 0; r < block.getRows(); r++) {
for (c = 0; c < block.getCols(); c++) {
assert(block.at(d, r, c) == d * 10000000 + r * 10000 + c);
}
}
}
return 0;
}
A smaller example (with changed names for all the structs, to make the general principle clearer). The 'Bloe' struct is the one you want to allocate on the heap, and this is accomplished using 'new'.
struct Bla {
int arr[4][4];
};
struct Bloe {
Bla bla[2][2];
};
int main()
{
Bloe* bloe = new Bloe();
bloe->bla[1][1].arr[1][1] = 1;
return 0;
}
I did this by putting all the data in a binary file. I calculated the offset of the data and used seek() and read() to get the data when needed. The open() call is very slow so you should leave the file open during the lifetime of the program.
Below is how I understood what you showed you were trying to do in your example. I tried to keep it straightforward. Each Array of [50][50][50] is allocated in one memory chunk on the heap, and only allocated when used. There is also an exemple of access code. No fancy boost or anything special, just basic C++.
#include <iostream>
class Block
{
public:
// Information about the blocks
int data;
};
class Grid
{
public:
bool empty;
Block (*blocks)[50][50];
Grid() : empty(true) {
}
void makeRoom(){
this->blocks = new Block[50][50][50];
this->empty = false;
}
~Grid(){
if (!this->empty){
delete [] this->blocks;
}
}
};
class Parent
{
public:
Grid (* child)[4][5];
Parent()
{
this->child = new Grid[5][4][5];
}
~Parent()
{
delete [] this->child;
}
};
main(){
Parent p;
p.child[0][0][0].makeRoom();
if (!p.child[0][0][0].empty){
Block (* grid)[50][50] = p.child[0][0][0].blocks;
grid[49][49][49].data = 17;
}
std::cout << "item = "
<< p.child[0][0][0].blocks[49][49][49].data
<< std::endl;
}
This could still be more simple and straightfoward and just use one bug array of [50][50][50][5][4][5] blocks in one memory chunk on the heap, but I'll let you figure out how if this is what you want.
Also, usind dynamic allocation in class Parent only has the sole purpose to use heap instaed of stack, but for such a small array (5*4*5 pointers), allocating it on stack should not be a problem, hence it could be written.
class Parent
{
public:
Grid child[5][4][5];
};
without changing anything in the way it is used.

Function that returns a pointer to const 2-d array (C++)

I'm an intermittent programmer and seem to have forgotten a lot of basics recently.
I've created a class SimPars to hold several two-dimensional arrays; the one shown below is demPMFs. I'm going to pass a pointer to an instance of SimPars to other classes, and I want these classes to be able to read the arrays using SimPars accessor functions. Speed and memory are important.
I know life is often simpler with vectors, but in this case, I'd really like to stick to arrays.
How do I write the accessor functions for the arrays? If I'm interested in the nth array index, how would I access it using the returned pointer? (Should I write a separate accessor function for a particular index of the array?) What's below is certainly wrong.
// SimPars.h
#ifndef SIMPARS_H
#define SIMPARS_H
#include "Parameters.h" // includes array size information
class SimPars {
public:
SimPars( void );
~SimPars( void );
const double [][ INIT_NUM_AGE_CATS ] get_demPMFs() const;
private:
double demPMFs[ NUM_SOCIODEM_FILES ][ INIT_NUM_AGE_CATS ];
};
#endif
// SimPars.cpp
SimPars::SimPars() {
demPMFs[ NUM_SOCIODEM_FILES ][ INIT_NUM_AGE_CATS ];
// ...code snipped--demPMFs gets initialized...
}
//...destructor snipped
const double [][ INIT_NUM_AGE_CATS ] SimPars::get_demPMFs( void ) const {
return demPMFs;
}
I would greatly appreciate some kind of explanation with proposed solutions.
Basically, you have three options: return the entire array by reference, return the first row by pointer, or return the entire array by pointer. Here is the implementation:
typedef double array_row[INIT_NUM_AGE_CATS];
typedef array_row array_t[NUM_SOCIODEM_FILES];
array_t demPMFs;
const array_t& return_array_by_reference() const
{
return demPMFs;
}
const array_row* return_first_row_by_pointer() const
{
return demPMFs;
}
const array_t* return_array_by_pointer() const
{
return &demPMFs;
}
And here are the use cases:
SimPars foo;
double a = foo.return_array_by_reference()[0][0];
double b = foo.return_first_row_by_pointer()[0][0];
double c = (*foo.return_array_by_pointer())[0][0];
How would I return just the nth row of the array?
Again, you have three choices:
const array_row& return_nth_row_by_reference(size_t row) const
{
return demPMFs[row];
}
const double* return_first_element_of_nth_row_by_pointer(size_t row) const
{
return demPMFs[row];
}
const array_row* return_nth_row_by_pointer(size_t row) const
{
return demPMFs + row;
}
const double (* get_demPMFs() const)[INIT_NUM_AGE_CATS];
Or, use typedef (but that doesn't seems cleaner...).
class SimPars {
typedef const double (*ConstDemPMFType)[INIT_NUM_AGE_CATS];
double demPMFs[NUM_SOCIODEM_FILES][INIT_NUM_AGE_CATS];
public:
ConstDemPMFType get_demPMFs() const;
};
Note that you can't return an array (g++ refuses the compile). But an array of array can be decayed to a pointer to array, so the latter is returned.
Logically speaking there is this question with a data member. Should users be allowed to modify it or not. If you want to give another class full access to the member, you don't necessarily need getter/setter, especially if you are the only user. You can just make the member public.
If your class would be better off controlling how users access the member, then you could use a getter only to enforce read only access. The simplest way to do this if you don't want to get all confused about the 2-dimensional arrays is to just have an inline function fetching the element for the user class:
const double& getElem( int x, int y ) const { return demPMF[x][y] }
It makes sense to do bounds checking here, but considering that you insist on using arrays, and if your profiler proves that you can't afford it, this function would just allow access to your array.
If you want further elaboration, post a comment...