0

I'm learning the basics of C++ with previous experience in Java based upon the official tutorial at "http://www.cplusplus.com/doc/tutorial/dynamic/". The tutorial presents the operator "new" as a way to define a array's size at runtime; however, this feels like a useless addition, since I can easily just define an array's size with a variable by doing

int numbers [size];

in contrast to

int * numbers = new int [size];

By testing on my own I already realized that using the new operator allows for going over the pre-allocated memory size (I could write to numbers[7] when I initialized it with size = 5), whereas the first line of code does not. I have three basic questions about this operator:

  1. What's the difference between the two lines of code above?
  2. Is it dangerous to write to a pointer address in memory in the array I didn't allocate to start with?
  3. If it is dangerous to do so, what alternative could I use (if there is one) to setting up lists other than manually setting up (or using a library for) a linked list?
Zach K
  • 264
  • 3
  • 10
  • 5
    " I can easily just define an array's size with a variable" Not in C++ you can't, only in C. Try putting your compiler in standard-compliant mode (`-std=c++17` or `-pedantic` command line options, usually) – Ben Voigt Aug 18 '19 at 04:40
  • 4
    *however, this feels like a useless addition, since I can easily just define an array's size with a variable by doing* -- [No you cannot do this](https://rextester.com/ACXHDS92193). -- *I'm learning the basics of C++ with previous experience in Java* -- Do not use Java as a guide in learning C++. They are two different languages, different rules, etc. – PaulMcKenzie Aug 18 '19 at 04:47
  • 1
    Also, use `std::vector` -- that's the way you do dynamic arrays in C++. Using `new[]` to do that job is "old style" and rarely, if ever, do you need to create dynamic arrays that way in this day and age of C++. Bottom line -- get yourself C++ books instead of going to websites to learn the language. – PaulMcKenzie Aug 18 '19 at 04:52
  • 2
    Do not touch Internet C++ tutorials with a six foot pole. Get a decent book updated for C++11 at least. A dynamic array in C++ is spelled with `std::vector`. Any source that attempts to teach you `new` before `std::vector` is seriously flawed (I'm being extremely polite here). – n. m. could be an AI Aug 18 '19 at 04:56
  • Do not and never use new. Do not and never use plain C-Style array in C++. Use STL container or other classes for that – A M Aug 18 '19 at 12:01

3 Answers3

3
int numbers [size];

in contrast to

int * numbers = new int [size];

The first, in standard C++, requires the value of size to be known and fixed at compile time. The second allows the value of size to be determined at run time (e.g. based on user input).

Some compilers allow the first form to be used with size as a variable, but that is not standard C++. Such variable length arrays are a feature of C (from 1999) that some C++ compilers support as a non-standard extension. Other C++ compilers will diagnose an error (as required by the C++ standard).

How the first is allocated depends on context. For example;

  • If outside a function (e.g. at file scope) it will be allocated statically, and will exist for as long as the program runs.
  • If inside a block (e.g. in a function) arr will have automatic storage duration and will cease to exist at the end of enclosing block (e.g. when the function returns).
  • If a member of a struct or class type, the array will be created whenever an instance of that struct or class is created.

The first two above are, somewhat incorrectly, sometimes said to be created on "the stack". However, the C++ standard does not require that - "the stack" is an implementation detail associated with operating systems and runtime environment.

The second is said to allocate memory dynamically (using operator new). The memory will exist until it is explicitly released (e.g. using the corresponding operator delete).

Is it dangerous to write to a pointer address in memory in the array I didn't allocate to start with?

Yes. The behaviour is undefined by the C++ standard. Practically, it can seem to work correctly. It can also have unwanted effects, such as poisoning data used by your program or reformatting your hard drive. In nasty cases, it can seem to work correctly in your testing, only to have one of the unwanted effects when run by a paying client. Such occurrences tend to make for grumpy clients.

The behaviour is equally undefined whether working with a pointer or an array. Assigning a value to the tenth element of an array with five elements gives undefined behaviour, regardless of how the array is created (e.g. in either of your two options).

If it is dangerous to do so, what alternative could I use (if there is one) to setting up lists other than manually setting up (or using a library for) a linked list?

In C++, there are standard containers. Look up vector (in the standard header <vector>) for an example. Obviously it is possible to use a standard container incorrectly (and get unwanted effects) but it is easier to avoid problems using a standard container than it is with arrays or pointers.

Standard containers also handle memory allocation and deallocation automatically - there is no need for you, as the programmer, to manage dynamic memory directly (e.g. forgetting to release the memory when no longer needed).

Community
  • 1
  • 1
Peter
  • 35,646
  • 4
  • 32
  • 74
2

What's the difference between the two lines of code above?

Assuming size is a constant expression, the difference is the first example is allocated on stack while the second on heap and you need to remember to delete [] it.

Is it dangerous to write to a pointer address in memory in the array I didn't allocate to start with?

It's undefined behaviour to write outside bounds, but if you're within bounds you're ok:

constexpr int size = 5;
int arr[size];
arr[0] = 2;

If it is dangerous to do so, what alternative could I use

Use a std::vector:

std::vector<int> arr;
Andreas DM
  • 10,685
  • 6
  • 35
  • 62
  • You might want to edit your answer on using vector to `std::vector arr(size);` which then can used similarly to the OP's examples. Note that `size` does not have to be a compile time const. – doug Aug 18 '19 at 05:20
0

What's the difference between the two lines of code above?

The difference is that the first one is not allowed in C++. Some compilers will allow it and may give a warning when special flags are supplied, whereas other compilers retch at the sight of it).

The second one is the way to go and pretty much does the same thing no matter what compiler you use.

Is it dangerous to write to a pointer address in memory in the array I didn't allocate to start with?

Yes it is. The behavior is undefined. If you don't get any exception at runtime, don't take that as a good thing because sooner than later, something will break surprisingly.

If it is dangerous to do so, what alternative could I use (if there is one) to setting up lists other than manually setting up (or using a library for) a linked list?

Are you asking for an alternative way to access memory that does not belong to you? The answer is DON'T DO IT!.

You can use one of C++'s containers as an alternative to creating a list of stuff. For a builtin linked list data structure, use std::list or std::forward_list. For random access containers, std::vector is a great start, but if you know the size ahead of time (i.e. before runtime), then std::array is the way to go.

smac89
  • 39,374
  • 15
  • 132
  • 179
  • `std::array` is only usable if the size is known at compile time. If the size is known and fixed at runtime then just use `std::vector` and reserve the space at construction time and performance is still great – phuclv Aug 18 '19 at 05:14