Jump to content

  • Log In with Google      Sign In   
  • Create Account


Stack Overflow? (Operator Overloading)


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
20 replies to this topic

#1 coderWalker   Members   -  Reputation: 127

Like
0Likes
Like

Posted 17 June 2011 - 07:45 AM

I keep getting a stack overflow error when running the below code.
Can anyone tell me why this is?

Thanks

//Create the array
	char testWorld[25*16][25*16][25*16];
	//Populate the array
	for (int z=0; z<25*16; z++)
	{
		for (int y=0; y<25*16; y++)
		{
			for (int x=0; x<25*16; x++)
			{
				testWorld[x][y][z] = testWorld[x+16][y][z];
			}
		}
	}
	//Move the array
	fps->start();
	for (int z=0; z<25*16; z++)
	{
		for (int y=0; y<25*16; y++)
		{
			for (int x=0; x<24*16; x++)
			{
				testWorld[x][y][z] = testWorld[x+16][y][z];
			}
		}
	}
	cout << fps->get_ticks();

If this post was helpful please +1 or like it !

Webstrand

Sponsor:

#2 PrestoChung   Members   -  Reputation: 177

Like
0Likes
Like

Posted 17 June 2011 - 07:50 AM

Someone correct me if I'm wrong but I think you need to use operator new if you want to allocate on the heap IE your stack is too small.

#3 Soul Reaver   Members   -  Reputation: 108

Like
1Likes
Like

Posted 17 June 2011 - 07:52 AM

I keep getting a stack overflow error when running the below code.
Can anyone tell me why this is?

Thanks

//Create the array
	char testWorld[25*16][25*16][25*16];
	//Populate the array
	for (int z=0; z<25*16; z++)
	{
		for (int y=0; y<25*16; y++)
		{
			for (int x=0; x<25*16; x++)
			{
				testWorld[x][y][z] = testWorld[x+16][y][z];
			}
		}
	}
	//Move the array
	fps->start();
	for (int z=0; z<25*16; z++)
	{
		for (int y=0; y<25*16; y++)
		{
			for (int x=0; x<24*16; x++)
			{
				testWorld[x][y][z] = testWorld[x+16][y][z];
			}
		}
	}
	cout << fps->get_ticks();


Your array is just to big for the Stack. You'll need to allocate it dynamically.

#4 mrbastard   Members   -  Reputation: 1568

Like
0Likes
Like

Posted 17 June 2011 - 07:52 AM

Because you're trying to allocate 64000000 bytes on the stack, and the stack has a maximum size.

You can increase the maximum stack size, but you'd probably be better off just allocating this big array on the heap instead - i.e. use new char[blah]

(ninja'd)

Posted Image


#5 rip-off   Moderators   -  Reputation: 7623

Like
0Likes
Like

Posted 17 June 2011 - 09:26 AM

Consider using a dynamic container like std::vector<char> instead of manually managing dynamic memory.

#6 coderWalker   Members   -  Reputation: 127

Like
0Likes
Like

Posted 17 June 2011 - 09:27 AM

It seems I can only allocate a 1deminsional array dynamically.
char* testWorld;
testWorld = new char [25*16*25*16*25*16];

Would I have to access the elements like this?
testWorld[(x*400*400)+(y*400)+(z)]
Is that math correct?

Is it possible to be able to access the elements like the following?
testWorld[x][y][z]

Consider using a dynamic container like std::vector<char> instead of manually managing dynamic memory.


All I need is the 64mb char's in memory, the size wont change, only the data. Wouldn't a vector be overkill?
If this post was helpful please +1 or like it !

Webstrand

#7 rip-off   Moderators   -  Reputation: 7623

Like
0Likes
Like

Posted 17 June 2011 - 09:44 AM

You can write a wrapper class:
#include <vector>

template<typename T>
class Array3D
{
public:
    Array3D(int width, int height, int depth) 
    :
        width(width),
        height(height),
        depth(depth), 
        storage(width * height * depth)
    {
    }

    T &operator()(int x, int y, int z)
    {
        return storage[index(x,y,z)];
    }

    const T &operator()(int x, int y, int z) const
    {
        return storage[index(x, y, z)];
    }

private:
    int index(int x, int y, int z) const
    {
        return (x * width * height) + (y * height) + z
    }

    int width;
    int height;
    int depth;
    std::vector<T> storage;
};
You index using array(1,7,42) rather than using square brackets, but it isn't too bad. You could use boost::multi_array, but I find it very ugly.

Wouldn't a vector be overkill?

Vector is pretty lean. I prefer not to mix the raw memory management with other logic. You could use a fixed array like boost::array as the underlying storage.

#8 coderWalker   Members   -  Reputation: 127

Like
0Likes
Like

Posted 17 June 2011 - 09:50 AM

Man that array3d class is pretty slick I think I may implement that.

The only thing is would that be slower than a standard 3d array because we have to calculate the index?
return (x * width * height) + (y * height) + z

If this post was helpful please +1 or like it !

Webstrand

#9 rip-off   Moderators   -  Reputation: 7623

Like
0Likes
Like

Posted 17 June 2011 - 10:04 AM

You change the width, height and depth to be template parameters, which would cause it to be evaluated (as much as possible) at compile time. This could cause code bloat if you create many instances of this class with varying sizes and types.

You could write an iterator type. This would allow you to use direct pointer increments for accessing each element when you don't need random access.

I don't know if it would cause as much trouble as you are worrying about. The modern CPU tends to be waiting for memory, it will likely have plenty of time to do that math =]

#10 Anthony Serrano   Members   -  Reputation: 1092

Like
0Likes
Like

Posted 17 June 2011 - 10:16 AM

Man that array3d class is pretty slick I think I may implement that.

The only thing is would that be slower than a standard 3d array because we have to calculate the index?

return (x * width * height) + (y * height) + z


The index has to be calculated like that anyway - the only difference with a standard array is that the compiler will generate the code automatically when compiling.

#11 coderWalker   Members   -  Reputation: 127

Like
0Likes
Like

Posted 17 June 2011 - 12:17 PM

I modified what rip-off presented optimized to what it needs to do, again using just a plain char* because I cannot afford any overhead.

array3d.h
class array3D
{
public:
	array3D(int size) : size(size)
	{
		data = new char[size*size*size];
	}
	char operator()(int x, int y, int z)
	{
    	return data[index(x, y, z)];
	}
	char operator()(int x, int y, int z) const
	{
    	return data[index(x, y, z)];
	}
private:
	int index(int x, int y, int z) const
	{
    	return (x * size * size) + (y * size) + z;
	}
	int size;
	char* data;
};

However I need to also overload the = operator to allow the following:

testWorld(x,y,z) = testWorld(x+16,y,z);
testWorld(x,y,z) = 1;


How would I do this? Is it possible? It would require the () operator and the = operator to be overloaded at the same time.
If this post was helpful please +1 or like it !

Webstrand

#12 CableGuy   Members   -  Reputation: 825

Like
0Likes
Like

Posted 17 June 2011 - 12:26 PM

make operator () return a reference to char.

#13 coderWalker   Members   -  Reputation: 127

Like
0Likes
Like

Posted 17 June 2011 - 12:35 PM

Can you elaborate a little more?

How will this help me assign values?

Oh you mean this? :
class array3D
{
public:
        array3D(int size) : size(size)
        {
        data = new char[size*size*size];
        }
        char &operator()(int x, int y, int z)
        {
        return data[index(x, y, z)];
        }
        char &operator()(int x, int y, int z) const
        {
        return data[index(x, y, z)];
        }
private:
        int index(int x, int y, int z) const
        {
        return (x * size * size) + (y * size) + z;
        }
        int size;
        char* data;
};

How exactly does this work?
Does it return the memory location instead of the data?

If this post was helpful please +1 or like it !

Webstrand

#14 iMalc   Crossbones+   -  Reputation: 2252

Like
0Likes
Like

Posted 17 June 2011 - 01:31 PM

I modified what rip-off presented optimized to what it needs to do, again using just a plain char* because I cannot afford any overhead.

You didn't optimise it in any way by removing the template argument. All that did is made it less generic / less useful. In fact to optimise it better you should have added more template parameters so that the size is known at compile time.

Going back to the far better code that rip-off started with and making a few tweaks...
array3d.h
template<typename T, int width, int height, int depth> 
class Array3D 
{ 
public: 
    Array3D() : storage(width * height * depth) 
    { 
    } 

    T &operator()(int x, int y, int z) 
    { 
        return storage[index(x,y,z)]; 
    } 

    T operator()(int x, int y, int z) const 
    { 
        return storage[index(x, y, z)]; 
    } 

private: 
    static int index(int x, int y, int z)
    { 
        return ((x * width + y) * height) + z;
    } 

    std::vector<T> storage; 
};

...

Array3D<char, 25*16, 25*16, 25*16> testWorld;
testWorld(x,y,z) = testWorld(x+16,y,z);
testWorld(x,y,z) = 1;
This does all that you want it to do. Heck, I even saved you a multiplication, although in the code I presented here, the compiler would have sorted that out.

Boost array does all this stuff for you also, so you may wish to look into that.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms

#15 CableGuy   Members   -  Reputation: 825

Like
0Likes
Like

Posted 17 June 2011 - 01:44 PM

Just a slight note that also for the const operator it is better to return a const reference since T might be a class
which might result in unnecessary copy constructors.

How exactly does this work?
Does it return the memory location instead of the data?

Well basically yes but how the compiler implements references shouldn't matter. The end result is that when changing a reference to X, the changes are applied to X itself.

#16 Álvaro   Crossbones+   -  Reputation: 11709

Like
0Likes
Like

Posted 17 June 2011 - 01:55 PM

You can regain the familiar array[x][y][z] notation by writing an operator[] that returns a proxy object. which provides an operator[] that returns another proxy object, which provides an operator[] that returns a reference to the correct element. It's a neat little exercise if you are trying to learn about operator overloading in C++.

#17 CableGuy   Members   -  Reputation: 825

Like
0Likes
Like

Posted 17 June 2011 - 02:03 PM

Correct me if I'm wrong but passing the dimensions of the array as a template parameter prevents you from writing something like this:
Array3D<char, width, height, depth> array;

assuming width, height and depth are not const?

#18 way2lazy2care   Members   -  Reputation: 782

Like
0Likes
Like

Posted 17 June 2011 - 02:23 PM

just write a one dimensional array and be good at math. Screw everyone else's optimizations... /not srs.

I'd just use boost. It will give you a lot of benefits all over your project.

this coming from someone that every day looks at a sprawling legacy codebase in which he can't even use STL containers. :'(

#19 Álvaro   Crossbones+   -  Reputation: 11709

Like
0Likes
Like

Posted 17 June 2011 - 03:26 PM

[...]
this coming from someone that every day looks at a sprawling legacy codebase in which he can't even use STL containers. :'(


Sorry about that. I work in an environment where for the most part I can't use exceptions or multiple threads, because I am working with tons of legacy code that wasn't written with any regard to such things, and it's bad enough. I they take the STL away from me I might just quit. :)

#20 scgames   Members   -  Reputation: 1969

Like
0Likes
Like

Posted 17 June 2011 - 04:42 PM

again using just a plain char* because I cannot afford any overhead.

The only way I can see use of std::vector adding any overhead would be if, for some reason, accessing the vector data via the [] operator were slower than accessing a raw array. However, I wouldn't assume that would be the case; if you have your optimization settings set appropriately (including the relevant preprocessor definitions if you're using MSVC), I would expect vector::operator[]() to be plenty fast. (But, you can always profile to find out for sure.)

On the other hand, *not* using an RAII container can add a fair amount of development overhead in terms of coding, testing, debugging, and maintenance. (For example, you now have to worry about the 'rule of three', exception safety, and so on.)

Note that I'm not advocating for any particular approach here; I'm just suggesting that making assumptions when it comes to performance and optimization can sometimes result in doing extra work for little or no gain.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS