8

Hey everyone. I am an experienced java programmer and am just learning C++.

Now I have a bit of a beginner's problem. I have an array variable x of type int.

The user will input the size of x in method B. I want to use x in method A.

void method A()
{
 using int x [] blah blah blah
}

void method B()
{
int n;
cin >>n;
int x [n]; // How can I use this int x in method A without getting error: storage size x is unknown.
// Or the error 'x' was not declared in this scope.
}

EDIT: Parameter passing isn't a solution I am looking for.

DOUBLE EDIT: I do know about the vector option, but my program is cramming on time. I am creating an algorithm where every millisecond counts.

BTW I found out a way of doing it.

int x [] = {}

method B();
method A () { blah blah use x}
method B () {/*int*/ x [n]}
Jimmy Huch
  • 4,400
  • 7
  • 29
  • 34
  • 4
    Not directly answering your question, but do get a good book. Here is a list: http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – Robᵩ May 06 '11 at 17:40
  • 2
    If I am reading your pseudo-code correctly, you have created an array as a local variable in `method B`. If that is the case, you should realize that the local `x` hides the definition of the global `x`. That is, the data you write to `x` in `B` won't affect the global `x`, and won't be visible in `A`. – Robᵩ May 06 '11 at 17:56
  • 2
    What's with all the downvoting? I posted my answer before the EDIT2 was posted. Also, @Jimmy Huch: if every nanosecond counts, use an array. If every day not spent debugging counts, use `std::vector` or `boost::scoped_array`. – Fred Foo May 06 '11 at 18:00
  • Sorry, an error in my code. in method B () it is supposed to be {x [n]} not int x [n] – Jimmy Huch May 06 '11 at 18:08
  • Jimmy, your "way of doing it" doesn't really work. Those are two completely distinct `x` variables. Things you declare in `B` have no effect on what `A` can do or see. Your original method B isn't valid C++ anyway (regardless of what you do in method A). – Rob Kennedy May 06 '11 at 18:12
  • @Jimmy - your way of doing it in your second edit produces undefined behavior. You haven't allocated an array; `{}` would give you nothing. You then are using random memory. I know you accepted my answer but it's an important thing to know. – Brian Roach May 06 '11 at 18:19

6 Answers6

9

If you actually want an array and not a vector, and you want that array dynamically sized at runtime, you would need to create it on the heap (storing it in a pointer), and free it when you're done.

Coming from Java you need to understand that there's no garbage collection in C++ - anything you new (create on the heap) in an object you will want to clean up in the destructor with delete.

class foo
{
    private:
    int *array;

    public:
    foo() { array = NULL; };
    ~foo()
    {
        if (array != NULL)
            delete [] array;
    }

    void createArray()
    {
        array = new int[5];
    }

};

More info at: http://www.cplusplus.com/doc/tutorial/dynamic/

Brian Roach
  • 76,169
  • 12
  • 136
  • 161
  • Finally someone who answers the question. – Seth Carnegie May 06 '11 at 17:55
  • 1
    This is the correct answer. Others want to give a C-style declaration, but that is wrong. Good job, +1 – Charles Ray May 06 '11 at 18:01
  • 1
    This code basically reinvents vector, but doesn't prevent you from leaking memory in createArray in addition to not providing a copy constructor or assignment operator leading to all sorts of problems if you ever copy it. – Mark B May 06 '11 at 18:18
  • 1
    Ah, so I should have answered the question he didn't ask, and later stated he didn't want. Then I should have worked up some complete class that didn't really have anything to do with the question. Got it. I'll remember that next time. – Brian Roach May 06 '11 at 18:20
3

This is a version of your example that works in c++.

#include <iostream>

int *my_array;

void methodA(a,b){
     my_array[a] = b;
}

int methodB(){
     int n;
     std::cin >> n;
     my_array = new int[n];
}

int main(){
     int x;
     x = methodB();
     methodA(x-1, 20);
     delete [] my_array;
     return 0;
}
Null Set
  • 5,374
  • 24
  • 37
1

Use a vector:

std::vector<int> x(n);

then pass that to method A as an argument of type std::vector<int> const &.

Edit: Or make the vector a data member of your class and set it with:

size_t n;
std::cin >> n;
x.resize(n);
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
1

In C++ you can't directly size an array with a runtime value, only with constants.

You almost certainly want vector instead:

std::vector<int> x(n);

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • @Charles Ray In C++ I don't see any particular reason to complicate things with pointers when `vector` will do. – Mark B May 06 '11 at 17:46
  • The question asked for an array, not a vector. That was my only consideration in my previous comment. According to OP, time is essential, so a vector would certainly NOT be useful. – Charles Ray May 06 '11 at 17:52
  • 2
    @Charles Ray Dynamic allocation and pointers will be pretty much equally performant to vector, with more risk of screwing up the memory management. There's no way to use a normal C-array with a runtime determined size, which is what the OP asked for. – Mark B May 06 '11 at 17:54
  • I managed to size an array with the variable n? My program works like a charm :) – Jimmy Huch May 06 '11 at 17:58
  • 1
    I'd like to see some data to back up such a bold claim. – Charles Ray May 06 '11 at 18:00
1

EDIT: flesh out answer.

I can't quite tell if you are trying to learn about arrays, or if you are trying to solve some practical problem. I'll assume the latter.

The only way for method A to have access to any variable is if it is in scope. Specifically, x must either be:

  • a local, including a parameter (but you said no to parameter passing)
  • a class member, or
  • a global

Here is a solution in which x is a class member:

class C {
public:
  std::vector<int> x;
  void A() {
    std::cout << x[2] << "\n"; // using x[], for example.
  }
  void B() {
    int n;
    cin >> n;
    x = std::vector<int>(n); // or, as others have pointed out, x.resize(n)
  }
};
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • Why do you have a std:: prefix to the vector declarations? – Jimmy Huch May 06 '11 at 17:51
  • 1
    Because the type `vector` is only available in the `std` namespace. If I didn't do that, I would get an undefined symbol error at compile time. – Robᵩ May 06 '11 at 17:54
  • I see. I have already become accustomed to putting using namespace std; at the beginnning of every program – Jimmy Huch May 06 '11 at 18:13
0

Be aware that arrays in C++ are much more basic (and dangerous) than in Java.

In Java, every access to an array is checked, to make sure the element number you use is within the array.

In C++, an array is just a pointer to an allocated area of memory, and you can use any array index you like (whether within the bounds of the array, or not). If your array index is outside the bounds of the array, you will be accessing (and modifying, if you are assigning to the array element!) whatever happens to be in memory at that point. This may cause an exception (if the memory address is outside the area accessible to your process), or can cause almost anything to happen (alter another variable in your program, alter something in the operating system, format your hard disk, whatever - it is called "undefined behaviour").

When you declare a local, static or global array in C++, the compiler needs to know at that point the size of the array, so it can allocate the memory (and free it for you when it goes out of scope). So the array size must be a constant.

However, an array is just a pointer. So, if you want an array whose size you don't know at compile time, you can make one on the heap, using "new". However, you then take on the responsibility of freeing that memory (with "delete") once you have finished with it.

I would agree with the posters above to use a vector if you can, as that gives you the kind of protection from accessing stuff outside the bounds of the array that you are used to.

But if you want the fastest possible code, use an allocated array:

class C {
 int [] x;

 void method A(int size)
 {
   x = new int[size];   // Allocate the array
   for(int i = 0; i < size; i++)
      x[i] = i;         // Initialise the elements (otherwise they contain random data)
   B();
   delete [] x;         // Don't forget to delete it when you have finished
                        // Note strange syntax - deleting an array needs the []
 }

 void method B()
 {
   int n;
   cin >> n;
   cout << x[n];
   // Be warned, if the user inputs a number < 0 or >= size, 
   // you will get undefined behaviour!
  }
}
Nikki Locke
  • 136
  • 1
  • 3
  • Wrong. new and delete can be one of the slowest parts of the whole system - typically they use malloc/free under the hood (plus whatever happens in the constructor for a c++ class, though that's not really relevant to the discussion). The amount of time it will take for malloc to find a free block of memory of the size you are requesting isn't deterministic - it can potentially take a really long time, so there's no guarantees. At least std::vector gives amortized time guarantees. – George May 08 '11 at 04:57
  • @George I am assuming however that once the array is actually initialised (i.e. once 'new' actually returns the memory), then it is faster than a vector? Or is that not the case? – Daniel Soutar Jul 26 '18 at 05:53