0

C++ newb here. I'm trying to write my own implementation of an array using only pointers, and I've hit a wall I don't know how to get over.

My constructor throws this error

array.cpp:40:35: error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]

When my array initializes I want it to free up all the spaces in the array for ints.

Array::Array(int theSize){
size = theSize;
int *arrayPointer = new int; 
int index = 0;
while(theSize > index){
  *(arrayPointer + index) = new int; //This is the trouble line.
  ++index;
 }
}

What am I doing wrong stackoverflow?

Breedly
  • 12,838
  • 13
  • 59
  • 83
  • 7
    Well, for starters you're attempting to allocate each element individually, when there's a built-in `new int[size]` syntax for array allocation ;-) – Cameron Aug 29 '12 at 21:33
  • Using `new int[size]` is just as bad (possibly worse). For a container, you normally want to use `buffer = operator new(size);` to allocate raw storage, followed by placement new to create objects in that space: `new(buffer+pos) int(value);` This matters little with `int`, but much more with other types. – Jerry Coffin Aug 30 '12 at 00:01
  • 1
    Since this comes up so often, and nearly always produces a slew answers I think are mostly wrong, I wrote up a [blog post](http://coderscentral.blogspot.com/2012/08/c-dynamic-arrays.html) about what I consider a better way to handle this. – Jerry Coffin Aug 30 '12 at 03:47

3 Answers3

1

arrayPointer points to a single int, it does not point to an array of int*, which this line would require:

*(arrayPointer + index) = new int;

but the type of *(arrayPointer + index) is an int, hence the compiler error.

To allocate an array of int:

int* arrayPointer = new int[size];

If this is intended to initialise a member variable then:

arrayPointer = new int[size];

otherwise arrayPointer would be local to the constructor. As the class now has a dynamically allocated member you need to either implement both copy constructor and assignment operator or prevent copying (see What is The Rule of Three?). Remember to delete[] arrayPointer in the destructor.


Just mentioning std::vector<int>, even though this is a learning exercise.

Community
  • 1
  • 1
hmjd
  • 120,187
  • 20
  • 207
  • 252
  • I tried new int[size] and the program hurled. Is there an include I need to use? – Breedly Aug 29 '12 at 21:39
  • Did you redeclare `arrayPointer` in the constructor (see updated answer)? – hmjd Aug 29 '12 at 21:40
  • Still hurling, forgot to post the error. `array.cpp:(.text+0x1c): undefined reference to operator new[] (unsigned int)'` Thanks for the link, I'll read more into it. – Breedly Aug 29 '12 at 21:50
  • @Breedly, what are compiler are using? GNU? If so, use `g++` and not `gcc`. – hmjd Aug 29 '12 at 21:52
  • Hah, problem solved, only to add more problems out of the scope of this question! Thanks so much, you were a huge help. Feel good about yourself for a few days. – Breedly Aug 29 '12 at 21:58
1

Do as follows:

#include <cstddef>

template <typename T>
class Array
{

public:

    T* const arrayPointer; // arrayPointer can't be reallocated
    const size_t size; // size can't change

    Array(const int theSize) : arrayPointer(new T[theSize]),
                               size(theSize) {}

    ~Array() {
        delete[] arrayPointer;
    }

private:

    Array(const Array& other) {} // forbid copy

    Array& operator= (const Array& other) {} // forbid assignment

} ;
  • Why to use template <typename T>? So you can have an array of any type.
  • Why to use new T[ theSize ] ? So you can allocate theSize elements at the same time.
  • Why to use : arrayPointer( new T[ theSize ]) ? So in case allocation fails (due to big theSize) the object fails without initialization. It is callled RAII.
  • Why to use delete [] arrayPointer ? Because you used new[] and you have to deallocate the whole array.
  • Why those const's? To avoid anyone changing the size of the array and making the fields inconsistent.
  • What are these private methods? They are forbiding copies, so no one can make array1 = array2; delete array2;, what would deallocate the arrayPointer of array1.

Usage (it will allocate array of 10 int:)

Array< int > arr( 10 ) ;

Access:

arr.arrayPointer[ 0 ] = 5 ;

Note - you can access arrayPointer at the cells of range 0..9. You can add operator[] to your class in order to avoid using arrayPointer and to use arr[ 0 ].

Alex Oliveira
  • 893
  • 1
  • 9
  • 27
Grzegorz
  • 3,207
  • 3
  • 20
  • 43
  • This is also a great answer, but it goes a little out of scope. You should feel good about yourself too for the next couple of days! – Breedly Aug 29 '12 at 21:59
  • @Breedly: I have just started feeling good about myself ;) Seriously, since you are a newbee to C++ then why not start the right way? And since you want to implement your ownr array, I think it is the best and safest way too. Have fun with C++. – Grzegorz Aug 29 '12 at 22:17
  • @Grzegorz Nice things to teach, but maybe too early. Now that you have shown that he needs a Destructor, you probably need to talk about the Rule of Three, otherwise it will not be "the best and safest way". – Alex Oliveira Aug 29 '12 at 22:42
  • @AlexOliveira: There is never end to how much one can learn ;) Yes, there is so much into it... pure C++ is really cool. – Grzegorz Aug 29 '12 at 22:52
  • @Grzegorz: Agree! I tried to edit you code to make it adhere to the Rule of Three without complicating it too much. – Alex Oliveira Aug 29 '12 at 23:15
  • @AlexOliveira: Thanks for the effort. Approved. – Grzegorz Aug 29 '12 at 23:18
0

The line you mentioned is trying to set a int* into a int var => Dereferencing a int* provide a int :

*(arrayPointer + index) // is a int

Anyway you are moving in memory (and dereferencing memory) you haven't reserved. So you can access a protected memory zone by doing this instruction.

Replace all your constructor with:

Array::Array(int theSize)
{
    size = theSize;
    arrayPointer = new int[theSize]; // Replace your local var with a member one. Else you will lose your array ;)
}
Patrice Bernassola
  • 14,136
  • 6
  • 46
  • 59