I am receiving "Segmentation fault" when I try to populate my array. So I was think of declaring the arrays size in the class to declare the array's size so it can allocate the space, but I receive.
error: invalid use of non-static data member ‘Array::Size’ error: from
this location
//Current
class Array{
public:
int Size;
int Range;
int Array[];
};
//Problematic
class Array{
public:
int Size;
int Range;
int Array[Size];
};
or there any other method of preventing an Segmentation fault?
You're attempting to use a C idiom, where the last member of a structure is a very short array (one or, if permitted by the compiler as a nonstandard extension, zero elements) and extra memory is allocated for the structure so elements beyond the end of the declared array can be accessed. This was originally a nonstandard trick, known as the struct hack, or in some compilers as zero-length arrays. It was standardized in C99 as flexible arrays.
When you used this idiom, you needed to allocate additional memory for the array, e.g. sizeof (struct Array) + sizeof (int) * number_of_elements. Otherwise you wouldn't have memory allocated for more elements than you actually declared (usually one or zero), and you'd get undefined behaviour when you tried to access elements beyond that.
However, you're writing C++, not C99. Even if your compiler allows you to do this, relying on it would be very bad practice, and a lot more awkward C++ than in C.
Either store a pointer in the class and allocate the appropriate amount of memory in the constructor, and deallocate it in the destructor, or use a C++ class that will manage the memory for you, e.g. std::vector.
Here's an example of using std::vector:
#include <vector>
class Array{
public:
int size;
int range;
std::vector<int> array;
Array(int size, int range) :
size( size ),
range( range ),
array( size, 0 )
{
}
};
Both these definitions
//Current
class Array{
public:
int Size;
int Range;
int Array[];
};
//Problematic
class Array{
public:
int Size;
int Range;
int Array[Size];
};
are invalid. The first one is invalid because class definition may not containg incomplete non-static data members. You may not write int Array[];
The second one is invalid because 1) data member Size has undefined value and 2) the size of an array shall be a constant expression.
Instead of declaring array you could use a pointer and dynamically allocate an array of the required size.
You can use pointer.
class Array{
public:
int Size;
int Range;
int* Array;
};
In the constructor, you can allocate memory for it. Or maybe you can do it in a member function.
Array::Array(/*parameters*/){
/* code */
Array = new int [Size] //After Size is initialized or assigned.
}
In the destructor, you should use delete[] Array to deallocate the memory.
Related
const int size = arraySize();
int list[size];
I get the following error:
expression must have a constant value
I know this may not be the best way to do it but it is for an assignment.
You should know that in C++ there are no dynamically allocated arrays.
Also, const variables are not necessarily known at compile time!
You can do one of the following:
Declare the function arraySize as constexpr, assuming you can calculate its value at compile time, or create a constant (again, with constexpr) which represents the array size.
Use dynamically allocated objects, such as std::vector (which is an "array" that can expand), or pointers. However, note that when you are using pointers, you must allocate its memory by using new, and deallocate using delete, which is error prone. Thus, I suggest using std::vector.
Using the first one, we get:
constexpr std::size_t get_array_size()
{
return 5;
}
int main()
{
constexpr std::size_t size = get_array_size();
int list[size];
}
which compiles perfectly.
Another thing which is nice to know is that there is std::array which adds some more functionality to the plain constant-size array.
Try dynamic allocation of this array.
int size = arraySize();
int* list;
list = new int [size];
It should work.
In addition, there is a condensed explanation of how dynamic arrays works: DynamicMemory
PS. Remember to free memory that you dynamically allocated, when it won't be needed:
delete [] list;
I am trying to statically allocate memory to an array of pointers to a struct called "mini". The "mini" structs serve as a way to store an index and the data so I can do an indirect sort by sorting a pointer to the struct. When I declare the array, the array is allocated memory to store the pointers, but the pointers themselves are not allocated any memory for the "mini" structs. It is important that it is statically allocated because it is part of a sorting algorithm, so I am trying to avoid dynamic memory allocation.
This is the declaration of mini and an array of pointers to mini:
typedef struct {
long long index;
string data;
} mini;
static mini* ssn[1010000];
I can dynamically allocate as follows:
for (int j = 0; j < 1010000; j++){
ssn[j] = new mini();
}
The problem arises when I try to statically allocate memory to each of the pointers. Here are a few things I have tried:
static mini* ssn[1010000] = {{0,""}};
static mini* ssn[1010000] = {{new mini()}};
None of these compile successfully.
Is there any way to statically allocate memory for each pointer in the array?
You have an array of pointers and you want to initialize the array (each pointer element) with a different value (allocation result). There is no way to do such initialization on declaration except to provide a value for each element:
static mini* ssn[4] = {new mini(), new mini(), new mini()};
Each element for which you haven't provided a value will be initialized with default value 0.
If you need a fixed-length array, it is better to use std::array. C++ have powerful type system, use it. In this case the initialization could be generalized:
struct Mini {
int x;
};
template <class Ar, class F, size_t... I>
static auto init(F factory, std::index_sequence<I...>) noexcept {
return Ar{factory(I)...};
}
using Array = std::array<Mini*, 20>;
static Array ssr(init<Array>([](...) { return new Mini(); }, std::make_index_sequence<20>()));
It is effectively the same:
static Array ssr(Array{new Mini(), new Mini(), ...})
The compiler will optimize the Array copy. Note, this solution requires c++14, although it could be adapted to c++11.
I am making a templated class holding a variable named array, and the user is allowed to change the size of this array. I am wondering how to deal with memory leaks?
templated <class T>
class MyClass{
long *array;
MyClass(long min, long max);
void Add(long n);
}
MyClass<T>::MyClass(long min, long max){
array= new long[min];
}
void MyClass<T>::Add(long n){
delete [] array;
array = new long[n];
}
(Yes, I know a vector would be better, but I must use arrays.)
Does this effectively change the size of the array to n and account for memory leaks?
When you have a class that dynamically allocates memory, you need a destructor to deallocate it. In your case, your MyClass destructor needs to also delete[] array;
I have a small C++ program defined below:
class Test
{
public:
int a;
int b[a];
};
When compiling, it produces an error:
testClass.C:7:5: error: invalid use of non-static data member ‘Test::a’
testClass.C:8:7: error: from this location
testClass.C:8:8: error: array bound is not an integer constant before ‘]’ token
How do I learn about what the error message means, and how do I fix it?
You cannot use an array with undefined size in compile time. There are two ways: define a as static const int a = 100; and forget about dynamic size or use std::vector, which is safer than the manual memory management:
class Test
{
public:
Test(int Num)
: a(Num)
, b(Num) // Here Num items are allocated
{
}
int a;
std::vector<int> b;
};
Unless you dynamically allocate them (such as with new[]), arrays in C++ must have a compile-time constant as a size. And Test::a is not a compile-time constant; it's a member variable.
Let's go through the complete reason behind this, first of all when you declare a class initially, any member variable has not been allocated any memory, so public or private methods have no value. That was a quick tip for you, now for your problem:
You can't do that outside the class since any array size should be known before the compilation because any statically declared array resides in the function's stack frame, and the compiler needs to know how much memory to allocate exactly. The only segment in memory that is resized by the programmer is the heap. So, whenever you want to have a dynamically allocated array size, you need to declare it to reside in the heap, and you do that like so:
int a;
cin >> a;
int * b = new int[a];
That's the correct way to declare an array with an unknown size (size determined during the runtime), to integrate this with your class here is how you do it, and recall that any class private or public attributes have no memory - They are just declarations that should not contain any initialization somewhere else in the member methods or outside the class - this is because they are public, as in your case - and of course after declaring an instance of the class e.g Test t. Anyway, here is how you do it within the class:
class Test
{
public:
int a;
int * b;
Test(int Ia=1) {
a = Ia;
b = new int[a];
}
~Test() {
delete[] b;
}
};
See delete vs delete[] operators in C++ for why to use delete[] instead of delete in the destructor.
This is really a noob quick question.
Imagine you have a struct called "No" and the following piece of code:
No *v_nos; // What does this mean?
Where I took this from they were calling "v_nos" a array? Isn't it simply a pointer to a struct "No"?
Thanks.
Arrays and pointers are NOT the same. In your case, the variable is a pointer, not an array. Even if they are not the same, the confusion is quite common and you will find in many places (including C/C++ books) that they are the same thing. This means that you should get acquainted to people calling pointers arrays.
When the C language was developed they decided that instead of passing arrays by value (possibly requiring a huge amount of copying and stack memory) they would convert silently the array into a pointer to the first element and then pass that pointer to the function.
void f( int a[3] ); // valid and misleading
// what it means:
// void f( int *a);
void test() {
int array[3];
f( array );
// what it means:
// f( & array[0] )
}
For backwards compatibility C++ keeps that feature around and you cannot pass arrays by value, nor define a function that takes an array by value (in both cases it will be converted to a pointer to the first element silently). At the same time, you can use the array access syntax on pointers to simplify pointer arithmetic, making it more confusing:
int array[3];
int *pointer = array; // simplified:
// int * pointer = & array[0]
pointer[2]; // equivalent to *(pointer+2) or array[2]
This means that with regular functions both in C and C++ arrays silently decay into pointers and most people will have the idea that they are the same thing: an array is a pointer to the first element. Well, they are not.
Both in C and C++ they are different entities, even if some usage patterns are equivalent due to that design decision. But they are in fact different:
int array[3]; sizeof(array); // 3*sizeof(int)
int *p1=array; // sizeof(int*), usually 4/8 bytes for 32/64 bit
int *p2=new int[3]; // sizeof(int*)
After passing through a function/method call, they are all pointers:
void f( int array[3] ) { sizeof(array); } // sizeof(int*) it is really a pointer! size is ignored
void g( int *p ) { sizeof(array); } // sizeof(int*)
In C++ things become even more interesting, as pass-by-value is not the only available paradigm and you can pass by reference:
void f( int (&array)[3] ); // funny syntax to pass an array of 3 integers by reference
void testf() {
int array1[3]; f(array1); // correct
int array2[2]; // f(array2); compilation error, it is not an array of 3 ints!
int *p = array1; // f(p); compilation error, it is not an array of 3 ints!
}
void g( int array[3] ); // means: void g( int *array );
void testg() {
int array1[3]; g(array1); // correct, the array decays into & array[0]
int array2[2]; g(array2); // correct, the array decays again
int *p = array1; g( p ); // correct it is a pointer
}
Note that when you define a function that takes an array by value you are actually defining a function that takes a pointer by value and that the compiler will not check that the argument to the function call actually has that size. This is a known source of errors and the reason why most functions that take arrays also take a size parameter.
Lastly, you cannot create arrays dynamically, you can only acquire memory dynamically into pointers, so when you need a heap allocated array you are actually in need of a pointer into a heap allocated contiguous block o memory:
void test() {
int *p = new int[3];
// int array[3] = new int[3]; // error!! an array is not a pointer
delete p;
}
At the end this all means that they are not the same thing, but that you can always use an array in the place of a pointer and it will be automatically converted by the compiler into a pointer to the first element of the array. More often than not, people will refer to pointers into a block of contiguously memory (whether stack or heap allocated) as array.
In terms of implementation, arrays and pointers are the same. That is, arrays are simply implemented as pointers to the first element in the array. The difference between
No *v_nos;
and
No v_nos[3];
Is that the latter sets aside memory for 3 elements for that array, while the pointer would need to have memory allocated using malloc (or new).
You could still treat the second one as the pointer that it is though, for example *v_nos would give you the first element, &v_nos would give the address of the pointer.
You are correct, but it can also be used as an array :
v_nos = new Nos[10];
v_nos[5].whatever = something;
// etc
Yes, it declares (but does not initialise) a pointer to a No.
Its a pointer to a No struct.
If they are calling it an array, that pointer could point to the first member of an array of No structs
for example
No* nos= getNosArray();//pseudocode
*nos;//first element
*(nos+1)//2nd element;
Arrays and pointers are more or less interchangeable in C++. You can dereference an offset from a pointer - *(v_nos+2) - and it's effectively the same as indexing an array v_nos[2]. In fact you can use either notation, IIRC. Under the covers both examples tell the compiler to do the same thing: increment the pointer by 2 * the size of the pointed-at object, and then return what it finds at that location.
typedef struct NO
{
int x;
}_NO;
int main()
{
_NO* v_nos;
_NO *v_nos_array;
v_nos = new _NO(); // allocate mem for 1 struct
v_nos_array = new _NO[100]; allocate mem for 100 structs
for(1=0; 1<100; i++) v_nos_array[i].x = i; //five some value to 'x' of each struct
for(1=0; 1<100; i++) cout << v_nos_array[i].x << "\n";
}
hope you can extract out the meaning. Note that an array with a single element is still an array.