views:

268

answers:

4

Hello,

So, I have this array. It needs to be accessed outside the scope of this function. I have been slapping a pointer to it into a pair which gets put into a deque. But once I'm outside the scope, the local stack is gone, the array is invalid, and I've just got a useless pointer, right?

So I've trying to put this array onto the scope-transcending heap, where it will remain until I delete it at a later time. But I'm having issues getting this working. Right now g++ is coughing up errors about invalid conversion from 'int' to 'int*'.

void randomFunction(int x, int y, int width, int height)
{
  int **blah[4] = {x, y, width, height};
  std::pair <foobar*, int* > tempPair (foobar1, blah);
  randomDeque.push_front(tempPair);
}

I've also tried initializing it like this:

int *blah[4] = new int[4];

...and it says that the array must be initialized with a brace-enclosed initializer.

I'm really not used to working with pointers. What am I doing wrong?

+1  A: 

The whole concept looks strange to me. If you declare array on the stack, it will not exist outside the scope of your function. If you allocate it using 'new' - make sure you 'delete' it sometime, otherwise it's memory leak! The correct code with 'new' is:

int *blah = new int[4];
...
// don't forget to:
delete [] blah;
Drakosha
A: 

It looks like you want a 4x4 array, in which case you should create it like so (untested code from the top of my head):

int **blah = new int* [4];
for(int i = 0; i < 4; ++i)
{
    *blah[i] = new int[4];
}

Alternatively you can create a 1D array and treat it like a 2D array:

int *blah = new int[16];
#define ELEM(x,y) w*4+h
blah[ELEM(1,1)] = 123;
badgerr
you highlight the code and then press ctrl-k, or the *code sample* button, to format it.
Nick D
Thanks Nick I was in a rush and couldn't find an obvious way to do it
badgerr
But... I don't *want* a 4x4 array. ;-)
James
Sorry I assumed you did since you were using a ** ;)
badgerr
+2  A: 

There are two problems. First, indeed, you are confused about pointers/arrays:

int a[4]; // this is an array of 4 integers, a is the name of the array
int *a[4]; // This is an array of 4 *pointers* to int

So your declaration:

int **blah[4];

Define an array of 4 pointers to pointers array. Maybe you are confused by the following fact (I know I was when I learned C). If you declare a variable:

int *a;

This is a declaration of a pointer to an integer. But if you have a variable a which is a pointer, you get the thing it points to (an integer here) by using *a:

*a = 1; // a is a pointer (i.e. an address), *a is the value pointed to by a.

So * in declaration is used to declare pointer, but * in statements is used to deference value.

But your second problem has nothing to do with pointer per-se. It is about ressource-management (memory being one, but file, locks being others). Anything allocated on the stack does not exist anymore when it is out of scope. In pure C, you only really have one solution: allocating on the heap with malloc, and making sure to free afterwards. So you would do something like:

// foo is a struct
foo *init_foo()
{
    foo* tmp;
    tmp = malloc(sizeof(*tmp));
    // initialize tmp

    return tmp;
}

And then, you will clean it with another function:

foo *a;
a = init_foo();
// do stuff
clean_foo(a);

Example: the FILE* handle and fopen/fclose (in addition to allocating stuff, there are some things related to the OS to handle the file). Another solution is to use alloca, which is not standard C, but is supported by many toolchains.

In C++, you can use smart pointers, which use for example reference counting to do resources management. I am less familiar with C++, and I am sure people will jump in on that part. The idea with reference counting is that it still gives some of the advantages of auto pointers (you don't have to call delete by yourself, which is extremely error-prone for non trivial projects), but without being purely scope-based. One reference counting-based smart pointer is shared_ptr in boost.

David Cournapeau
+1  A: 

I'm not sure if I got right what you want to do, but in case you want to return a reference to an int array which will be valid after randomFunction returns, a good way to do it is with Boost:

#include <boost/shared_ptr.hpp>
#include <vector>

boost::shared_ptr<std::vector<int> > randomFunction(int x, int y, int width, int height)
{
  boost::shared_ptr<std::vector<int> > blahPtr(new std::vector<int>(4));
  (*blahPtr)[0] = x;
  (*blahPtr)[1] = y;
  (*blahPtr)[2] = width;
  (*blahPtr)[3] = height;
  return blahPtr;
}

You don't have to remember about deleteing blahPtr -- when all copies of it go out of scope, Boost will delete your std::vector object automatically, and C++ standard library will delete the underlying array.

quant_dev