You are here:

C++/scope question

Advertisement


Question
Hello! Id like to ask a scope question if you have time. I have a function (function A) that creates an array of objects of type MyClass. Everything works great but I cannot access this array with my other functions. In order to make this array available I need to give it global scope (define it outside of any other function). However, I cannot do that either because once I declare an array outside the functions, I cannot later allocate it dynamically inside a function. So, I have a scope problem. I also tried to declare a pointer outside of functions like this:



extern MyClass *myArray;



and then within my function A I declare my array like this



MyClass *myArray[100];



This, surprsisingly, makes it possible for the other functions of the program to recognize myArray as a legitimate thing but creating a pointer like this (when done by a function other than function A) will never work:



MyClass *pointer=myArray[5];



This should work because when I do this in the function A, everything works.

What do you think Im doing wrong? Thank you for finding the time to help me!! - eric  

Answer
Hi, Eric.  Scope is absolutely the right word to use here.  The problem you're experiencing is that the array declared in the function exists only within the function.  Let me demonstrate with a few examples.


   void main()
   {
       int integer1 = 0;
       {
         int integer2 = 0;
       }

       int integer3 = integer1 + integer2;
   }

If you take this simple program and try to compile it, you will get a somewhat baffling compile error: 'integer2' undeclared identifier.  The reason for this is that integer2 has fallen out of scope.  The scope for integer2 exists only within the curly braces surrounding it.  Those curly braces may look entirely useless, since there is no if, while, or for loop associated with them, but they tell the compiler to generate a new scope and everything within them exists purely within that scope.

Similarly, in your function, everything declared within that function exists solely within the scope of that function, and cannot be accessed outside of that function:

   void myFunction()
   {
       int myArray[20] = { 0 };
       int myInt = 1;
   }

   void main()
   {
       myFunction();
       myArray[1] = myInt;
   }

Try to compile that and you will get the very same type of compile error.  Again, the reason is because myArray and myInt only exist within the function myFunction.  They cannot be accessed outside of myFunction.  In fact, when something falls out of scope, its memory can be used for other purposes.

The way around this is to use references or pointers.  You didn't give a concrete example of what you're trying to accomplish, so I hope my sample code is relevant.  I'll give a few examples of how you can accomplish this.  First, passing an array to a function:

   int sumArray(int* _pArray, int _numElements)
   {
       int nSum = 0;
       for (int i = 0; i < _numElements; ++i)
       {
         nSum += _pArray[i];
       }

       return nSum;
   }

   void main()
   {
       int myArray[10] = { 5, 2, -12, 63, 6, 9, -7, 13, 1, -20, };
       int myArraySum = sumArray(myArray, 10);
   }

See how the array is passed into the function and used?  Notice that not only the pointer to the start of the array must be handed over, but the size of the array is needed, as well.  This is a simple demonstration of a function which is flexible enough to support any sized array and perform the same type of operation on it.

Similarly, if you need to create an array, you can use dynamically allocated memory to create the array on the heap instead of the stack, thus ensuring that the array does not disappear when the function goes out of scope.  You must be careful to maintain a pointer to the memory so you can clean it up later, however:

   int sumArray(int* _pArray, int _numElements)
   {
       int nSum = 0;
       for (int i = 0; i < _numElements; ++i)
       {
         nSum += _pArray[i];
       }

       return nSum;
   }

   int* createArray(int _numElements)
   {
       int* pNewArray = new int[_numElements];
       return pNewArray;
   }

   void main()
   {
       int* myArray = createArray(10);
       myArray[0] = 5;
       myArray[1] = 2;
       myArray[2] = -12;
       myArray[3] = 63;
       myArray[4] = 6;
       myArray[5] = 9;
       myArray[6] = -7;
       myArray[7] = 13;
       myArray[8] = 1;
       myArray[9] = -20;
       int myArraySum = sumArray(myArray, 10);
       delete[] myArray;
   }

Obviously the createArray function in my example is fairly useless, but it shows you how you can create an array and hand it back to the caller, anyway.  Also, in my example, I call delete on a pointer handed back by another function.  This is generally bad practice.  A more correct approach would be to create a releaseArray function to handle the deletion for me.

If you need your function to return another value other than the allocated pointer, then you can pass a double pointer into the create function:


   int sumArray(int* _pArray, int _numElements)
   {
       int nSum = 0;
       for (int i = 0; i < _numElements; ++i)
       {
         nSum += _pArray[i];
       }

       return nSum;
   }

   void createArray(int _numElements, int** _pStorage)
   {
       if (!_pStorage)
         return;
       *_pStorage = new int[_numElements];
   }

   void main()
   {
       int* myArray = NULL;
       createArray(10, &myArray);
       myArray[0] = 5;
       myArray[1] = 2;
       myArray[2] = -12;
       myArray[3] = 63;
       myArray[4] = 6;
       myArray[5] = 9;
       myArray[6] = -7;
       myArray[7] = 13;
       myArray[8] = 1;
       myArray[9] = -20;
       int myArraySum = sumArray(myArray, 10);
       delete[] myArray;
   }

Notice that here, I create the pointer, then pass the address of the pointer, otherwise known as a double pointer, into the function.  The function verifies that the pointer to the pointer exists, then dereferences it, so that it is now accessing the original pointer, and stores the address of the allocated memory to that original pointer.  In this way, the function is free to return a different type than the pointer, such as an error code.  This is very useful.

OK, that about sums it up.  If I did not answer your question or if I raised new questions, feel free to let me know and I'll be happy to help.

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Joseph Moore

Expertise

I've been programming in one form or another since my brother taught me BASIC when I was 6. I've been programing professionally since I was 20, first web development with HTML, JS, DHTML, CSS, etc., then I became a video game developer, writing code in C, C++, C#, SQL, assembly, and various scripting languages. I've even written my own scripting languages, custom designed for the games I was making. I also dabble in Java, PHP, and Perl. I've worked on pretty much every aspect of game development, including graphics, audio, gameplay, tool, UI, input, animation, and physics.

Experience

I've been writing C++ code for 12 years, both on my own in my spare time and professionally.

Organizations
IGDA

Education/Credentials
Bachelor of Science in Game Design and Development, Full Sail University, Winter Park, FL

Awards and Honors
Salutatorian and Advanced Achiever Awards at Full Sail; Independent Games Festival Student Showcase winner, 2004; Featured article on Gamasutra about an experimental game developed in 2004

©2016 About.com. All rights reserved.