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) {
}
};
Related
I'm working with a dynamic array of a given class, let's call it 'MyClass', the thing is this class has a specialized constructor with a given parameter.
As far as I know to initialize a dynamic array I should use this:
MyClass *myArray = new MyClass[]();
Is there a way to initialize my array using my specialized constructor? something like:
MyClass *myArray = new MyClass[](givenParameter);
and this got me to another question, what does the line MyClass *myArray = new MyClass[](); is it calling a base constructor without any given parameters or does it do something else internally?
It may be something obvious but I wasn't able to find much information on this, at least not something to solve my first question. Thank you, everyone.
The syntax MyClass *myArray = new MyClass[size](); allows you to value-initialize the elements when they are trivial simple types (like integers, etc, thus setting them to 0), but it is not very meaningful for elements of class/struct types, so the () is usually omitted for those types. new[] can only call default constructors on class/struct types, it does not allow you to call non-default constructors.
However, a way to handle that is to use placement-new instead, which would then allow you to construct each MyClass object individually, even with different parameter values if needed.
// allocate raw memory to hold the objects array...
char *myArrayBuf = new char[sizeof(MyClass) * NumberOfItems];
/* alternatively, in C++11 and later:
#include <type_traits>
using element_type = std::aligned_storage<sizeof(MyClass), alignof(MyClass)>::type;
element_type *myArrayBuf = new element_type[NumberOfItems];
*/
// call the constructor on each object in the array...
MyClass *myArray = reinterpret_cast<MyClass*>(myArrayBuf);
for(int i = 0; i < NumberOfItems; ++i) {
new(&myArray[i]) MyClass(givenParameter);
}
// use myArray as needed ...
// call the destructor on each object in the array...
for(int i = 0; i < NumberOfItems; ++i) {
myArray[i].~MyClass();
}
// deallocate the raw memory for the array...
delete[] myArrayBuf;
In C++11 and later, this would be easier to handle using a std::vector instead (which you should be using anyway):
#include <vector>
std::vector<MyClass> myArray;
myArray.reserve(NumberOfItems);
for(int i = 0; i < NumberOfItems; ++i) {
myArray.emplace_back(givenParameter);
}
// use myArray as needed ...
Prior to C++11, you can still use std::vector, but it would require copy-constructing the array elements:
#include <vector>
std::vector<MyClass> myArray;
myArray.reserve(NumberOfItems);
for(int i = 0; i < NumberOfItems; ++i) {
myArray.push_back(MyClass(givenParameter));
}
// use myArray as needed ...
MyClass *arr;
arr = new MyClass[2]{{10, "hello"},{20, "custom constructor"}};
I'm not sure there's another way to initialize C-array with non-standard constructor.
But if you're ok with using std::vector then:
#include <vector>
size_t size = 2;
std::vector<MyClass> myArray(size, MyClass(givenParameter));
Does the following create x new objects, or simply allocate space for x objects?:
Vector3D* binArray = new Vector3D[size];
I need to build an array with space for x Vector3D objects on the heap. However, a Vector3D object can only be created when an "add" function is called - this will take the parameters, construct the object on the heap and add its address to the array of Vector3D pointers.
This does create an array of Vector3D objects on the heap.
Each vector is created by calling the Vector3D constructor.
Put a little debugging print statement in the default constructor for Vector3D, and watch the constructor get called the same number of times as you have vectors in your array.
Example:
#include <iostream>
using namespace std;
class C {
public:
C() { cout << "Hello default constructor here\n"; }
};
int main() {
C* cs = new C[5];
}
Output is:
Hello default constructor here
Hello default constructor here
Hello default constructor here
Hello default constructor here
Hello default constructor here
If your class does not have a default constructor, you cannot allocate the array in one shot (thank you for the comment #Everyone), so in this case consider using a std::vector or a std::array and adding your Vector3D objects dynamically --- or even "statically"! Example:
#include <iostream>
#include <vector>
using namespace std;
class Vector3D {
double i, j, k;
public:
Vector3D(double i, double j, double k): i(i), j(j), k(k) {}
};
int main() {
vector<Vector3D> v = {
Vector3D(3, 4, 5),
Vector3D(6, 8, 10),
Vector3D(7, 24, 25)
};
v.push_back(Vector3D(1, 2, 3));
cout << v.size() << '\n';
}
This outputs 4.
You can also make your vector contain pointers to Vector3D objects.
Just to add based on the asker's comments on RayToal's excellent answer. If you don't know the size of the binArray prior to runtime then you must use std::vector. If you want to allocate each item alone, I would recommend using std::vector<Vector3D*>.
This way you can resize the std::vector at runtime and when you do, it will hold a bunch of nullptrs that are not allocated. Then you can allocate each one of them separately.
std::vector<Vector3D*> binArray;
binArray.resize(x); // now you have binArray of size x and no allocated elements
binArray[0] = new Vector3D(...);
Please keep in mind that you need to delete them after you're not using them in order to not have a memory leak:
for(size_t i=0;i<binArray.size(); i++)
if(binArray[i]!=nullptr) delete binArray[i];
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 ;)
}
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?
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.,