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?
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.
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 ].
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 ;)
}
Related
I have come across some code which allocates a 2d array with following approach:
auto a = new int[10][10];
Is this a valid thing to do in C++? I have search through several C++ reference books, none of them has mentioned such approach.
Normally I would have done the allocation manually as follow:
int **a = new int *[10];
for (int i = 0; i < 10; i++) {
a[i] = new int[10];
}
If the first approach is valid, then which one is preferred?
The first example:
auto a = new int[10][10];
That allocates a multidimensional array or array of arrays as a contiguous block of memory.
The second example:
int** a = new int*[10];
for (int i = 0; i < 10; i++) {
a[i] = new int[10];
}
That is not a true multidimensional array. It is, in fact, an array of pointers and requires two indirections to access each element.
The expression new int[10][10] means to allocate an array of ten elements of type int[10], so yes, it is a valid thing to do.
The type of the pointer returned by new is int(*)[10]; one could declare a variable of such a type via int (*ptr)[10];.
For the sake of legibility, one probably shouldn't use that syntax, and should prefer to use auto as in your example, or use a typedef to simplify as in
using int10 = int[10]; // typedef int int10[10];
int10 *ptr;
In this case, for small arrays, it is more efficient to allocate them on the stack. Perhaps even using a convenience wrapper such as std::array<std::array<int, 10>, 10>. However, in general, it is valid to do something like the following:
auto arr = new int[a][b];
Where a is a std::size_t and b is a constexpr std::size_t. This results in more efficient allocation as there should only be one call to operator new[] with sizeof(int) * a * b as the argument, instead of the a calls to operator new[] with sizeof(int) * b as the argument. As stated by Galik in his answer, there is also the potential for faster access times, due to increased cache coherency (the entire array is contiguous in memory).
However, the only reason I can imagine one using something like this would be with a compile-time-sized matrix/tensor, where all of the dimensions are known at compile time, but it allocates on the heap if it exceeds the stack size.
In general, it is probably best to write your own RAII wrapper class like follows (you would also need to add various accessors for height/width, along with implementing a copy/move constructor and assignment, but the general idea is here:
template <typename T>
class Matrix {
public:
Matrix( std::size_t height, std::size_t width ) : m_height( height ), m_width( width )
{
m_data = new T[height * width]();
}
~Matrix() { delete m_data; m_data = nullptr; }
public:
T& operator()( std::size_t x, std::size_t y )
{
// Add bounds-checking here depending on your use-case
// by throwing a std::out_of_range if x/y are outside
// of the valid domain.
return m_data[x + y * m_width];
}
const T& operator()( std::size_t x, std::size_t y ) const
{
return m_data[x + y * m_width];
}
private:
std::size_t m_height;
std::size_t m_width;
T* m_data;
};
Firstly I wanted to say this is a HW assignment and I just have questions in regards to the errors I'm facing
I made a vector template with an insert function that adds a data_type to the end of a dynamic array. This is what I have currently.
// Insert the value at the specified index by moving the tail
// when Size = Capacity the Vector has to be reallocated first
// to accomate the new element
void Insert(const DATA_TYPE& value, int index){
// If the Capacity is not large enough then ...
// allocate large vector
if (Size >= Capacity){
// 0. Let's boost the capacity
Capacity += CAPACITY_BOOST;
// 1. Allocate new larger vector
DATA_TYPE* newData = new DATA_TYPE[Capacity];
// 2. Copy from old Data into the newData
for( int i=0; i< Size; i++)
newData[i] = Data[i];
// 3. Delete the old Data
delete[] Data;
// 4. Replace old Data-pointer with the newData pointer
Data = newData;
}
// Move the tail
for(int i=index; i<Size;i++){
Data[i+1] = Data[i];
}
// Insert
Data[index] = value;
Size++;
}
DATA_TYPE& operator[] (int index) const{
return *this[index];
}
Note: Using Private Variables: Size, Capacity, Data(stores the dynamic array)
I'm pretty sure I've implemented the add or push_back function correctly. The problem is when ever I try to cout something like "cout << a[1]; " I get an error.
while compiling class template member function 'int &Vector<DATA_TYPE>::operator [](int) const'
with
[
DATA_TYPE=int
]
see reference to class template instantiation 'Vector<DATA_TYPE>' being compiled
with
[
DATA_TYPE=int
]
error C2440: 'return' : cannot convert from 'const Vector<DATA_TYPE>' to 'int &'
with
[
DATA_TYPE=int
]
There should be 2 versions of your operator[]:
const DATA_TYPE& operator[] (int index) const;
DATA_TYPE& operator[] (int index);
What you have is a weird combination of the two.
You should also be returning
return Data[index];
Returning (*this)[index]; would result in an infinite recursive call (well, not infinite, you'll get a stackoverflow before that).
There are three problems here:
Operator precedence. *this[index] is parsed as *(this[index]), while you meant (*this)[index].
You're returning a mutable reference to your data from a const method.
The definition of operator[] is circular. Returning (*this)[index] in operator[] would cause infinite recursion.
The operator[] function is declared to be constant, i.e. it can't change anything in the Vector object. But it returns a reference, which means that the returned value can be modified. These two contradicts each other.
This can be solved by either remove the const from the end of the function, or to not return a reference.
I have a pointer to a class, that have a pointer to a multidimensional array but I can't seem to delete it from memory when I need to or set it to NULL.
#define X 10
#define Y 10
struct TestClass
{
public:
int *pArray[X][Y];
};
// different tries, none working:
delete Pointer_To_TestClass->pArray[0][0];
delete[] Pointer_To_TestClass->pArray[0][0]
// or by simply:
Pointer_To_TestClass->pArray[0][0] = NULL;
I know the array has data because I can see the results on screen.
Also check if it's NULL already, then doesn't try to delete it.
Since I want to delete a pointer in another pointer - is this a special circumstance that works differently? Like it deletes the first pointer holding the other pointer instead of the pointer inside the pointer (pArray is the second pointer, Pointer_To_Testclass is the first pointer)
UPDATE/EXPLANATION
I want to be able to delete pArray[0][0] while pArray[0][1] still exists and if [0][0] doesn't exist it should be equal to NULL. Most because I want to access this array by [X][Y] values for easy access. If [0][0] is a pointer, it should be NULL when deleted so I can check if it is NULL.
Anyone has any ideas?
If you want a 2D array of pointers to <whatever>, create a class to handle that, then put an instance of it in your TestClass. As far as how to do that, I'd generally use something on this order:
template <class T>
class matrix2d {
std::vector<T> data;
size_t cols;
size_t rows;
public:
matrix2d(size_t y, size_t x) : cols(x), rows(y), data(x*y) {}
T &operator()(size_t y, size_t x) {
assert(x<=cols);
assert(y<=rows);
return data[y*cols+x];
}
T operator()(size_t y, size_t x) const {
assert(x<=cols);
assert(y<=rows);
return data[y*cols+x];
}
};
class TestClass {
matrix2d<int *> array(10, 10);
public:
// ...
};
Given that you're storing pointers, however, you might want to consider using Boost ptr_vector instead of std::vector.
#define X 10
#define Y 10
struct TestClass
{
public:
TestClass()
{
// Must initialize pArray to point to real int's otherwise pArray
// will have bogus pointers.
for (size_t y = 0; y < Y; ++y)
{
for (size_t x = 0; x < X; ++x)
{
pArray[x][y] = new int;
}
}
}
int *pArray[X][Y];
};
int main()
{
TestClass *Pointer_To_TestClass = new TestClass;
delete Pointer_To_TestClass->pArray[0][0];
Pointer_To_TestClass->pArray[0][0] = 0;
return 0;
}
Depends on your allocation of pArray[i][j]. If it's something like pArray[i][j] = new int; then call delete Pointer_To_TestClass->pArray[0][0];. If it's something like pArray[i][j] = new int[10] then use your second option, delete[] Pointer_To_TestClass->pArray[0][0];. I'd also highly recommend immediately following the delete with setting it to NULL and proceeding it with the check for NULL.
The third one did not compile for me delete[][] Pointer_To_TestClass->pArray[0][0]; I got the error
Line 34: error: expected primary-expression before '[' token
compilation terminated due to -Wfatal-errors.
Also, I'd highly recommend having those deletes in the destructor. Other places may be fine as well.
You may find the typedef of int* to be helpful for readability understanding you have a two-dimensional array of int*.
If you've dynamically created an array, then delete it with delete[]. You have to give delete[] a pointer to the start of the array, however, not an element of the array!
If you want the elements to be deletable, then they have to be dynamically allocated separately.
So you have to have a multi-dimensional array of pointers;
int *(*pArray)[X][Y];
Then dynamically assign each one, which yes is a pain.
It is interesting, however, that you are even attempting to do this, why do you want to delete single elements?
I have:
class first{
private:
int *array;
public:
first(int x){
array = new int[x][10];
}
I want to call this class by:
first class1 = new first(10);
Why it doesn't work ? How to inintialize array by size from constructor ??
Just this is enough:
first class1(10);
new is for when you're allocating a pointer.
first *class1 = new first(10);
Furthermore, you have an incompatibility here:
array = new int[x][10];
array is an int*, but new int[x][10] is a 2D array. I'm not sure which one you want.
For the 1D array:
int *array;
array = new int[x];
For the 2D array:
int (*array)[10];
array = new int[x][10];
That said, you might be better off using std::vector.
Side Note: Since you have memory allocation in the constructor, you should also implement a destructor, copy-constructor, and copy-assignment operator.
You've indicate that you want a one-dimensional array (int*) but attempted to allocate a two-dimensional array (new [x][10]).
I'll assume you need one dimension.
The C++ way to do this is with vector.
#include <vector>
class first{
private:
std::vector<int> array;
public:
explicit first(int x) : array(x) {
}
};
It is possible to give an initializer list to the definition of a static array. Example:
int main()
{
int int_static[2] = {1,2};
}
Is a similar initializer list possible for a dynamic array?
int main()
{
int* int_ptr = new int[2];
}
This is closer to what I am trying to do:
struct foo
{
foo(){}
foo(void * ptr): ptr_(ptr) {}
void * ptr_;
};
int main()
{
foo* foo_ptr = new foo[10];
}
At initialization time not the default constructor should be called, but foo:foo(void*).
The point of having a static initializer list for a dynamic array might come handy in the case of Just-In-Time compilation for accelerator cores which do have only a limited amount of stack available, but at the same time you construct your objects with a (accelerator compile time = host run time) static initializer list.
I assume not (since this would require the compiler to generate additional code, namely to copy the values of the arguments to the heap location). I think c++0x supports some of this, but I cannot use it.
Right now I could use such a construct. Maybe someone knows a trick..
Best!
At the time the OP posted this question, C++11 support may not have been very prevalent yet, which is why the accepted answer says this is not possible. However, initializing a dynamic array with an explicit initializer list should now be supported in all major C++ compilers.
The syntax new int[3] {1, 2, 3} was standardized in C++11. Quoting the new expression page on cppreference.com:
The object created by a new-expression is initialized according to the following rules:
...
If type is an array type, an array of objects is initialized:
...
If initializer is a brace-enclosed list of arguments, the array is aggregate-initialized. (since C++11)
So, given the OP's example, the following is perfectly legal when using C++11 or newer:
foo * foo_array = new foo[2] { nullptr, nullptr };
Note that by providing pointers in the initializer list, we're actually coaxing the compiler to apply the foo(void * ptr) constructor (rather than the default constructor), which was the desired behavior.
No, you cannot do that.
I think C++ doesn't allow this because allowing such thing doesn't add any nice-to-have feature to the language. In other words, what would be the point of dynamic array if you use a static initializer to initialize it?
The point of dynamic array is to create an array of size N which is known at runtime, depending on the actual need. That is, the code
int *p = new int[2];
makes less sense to me than the following:
int *p = new int[N]; //N is known at runtime
If that is so, then how can you provide the number of elements in the static initializer because N isn't known until runtime?
Lets assume that you're allowed to write this:
int *p = new int[2] {10,20}; //pretend this!
But what big advantage are you getting by writing this? Nothing. Its almost same as:
int a[] = {10,20};
The real advantage would be when you're allowed to write that for arrays of N elements. But then the problem is this:
int *p = new int[N] {10,20, ... /*Oops, no idea how far we can go? N is not known!*/ };
No, you will have to create the elements dynamically.
Alternatively, you can use a local array and copy its elements over those of the dynamically allocated array:
int main() {
int _detail[] = { 1, 2 };
int * ptr = new int[2];
std::copy( _detail, _detail+(sizeof detail / sizeof *detail), ptr );
delete [] ptr;
}
In the limited version of setting all elements to 0, you can use an extra pair of parenthesis in the new call:
int * ptr = new int[2](); // will value initialize all elements
But you seem to be looking for a different thing.
Given that you're real class is more complex than an int, and constructed from differing values, it's complicated.
A vector can be constructed with iterators if you have an existing array/vector with the correct values to default from, or you have to use placement new.
//vector
int main()
{
int int_static[2] = {1,2};
std::vector<int> int_dynamic(int_static, int_static+2);
//this is what everyone else is saying. For good reason.
}
//placement new
int function_that_returns_constructed_from_values() {
return rand();
}
int main()
{
int count = 2;
char *char_dynamic = new char[count * sizeof(int)];
int *int_dynamic = char_dynamic;
for(int i=0; i<count; ++i)
new(int_dynamic+i)int(function_that_returns_constructed_from_values());
//stuff
for(int i=0; i<count; ++i)
(int_dynamic+i)->~int(); //obviously not really int
delete []char_dynamic;
}
Obviously, the vector is the preferred way to do this.
The initializer data must be somewhere anyway. Simply name it.
E.g.,
#include <stddef.h>
#include <algorithm> // std::copy
#include <vector>
typedef ptrdiff_t Size;
template< class Type, Size n >
Size countOf( Type (&)[n] ) { return n; }
int main()
{
using namespace std;
static int const initData[] = {1,2};
static Size const n = countOf( initData );
// Initialization of a dynamically allocated array:
int* pArray = new int[n];
copy( initData, initData + n, pArray );
// Initialization of a vector:
vector<int> v( initData, initData + n );
}
EDIT: fixed a thinko in above code. I hastened to add example on request. So what I put did erroneously use return value from std::copy.
Cheers & hth.,