Array[n] vs Array[10] - Initializing array with variable vs numeric literal - c++

I am having the following issue with my code:
int n = 10;
double tenorData[n] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Returns the following error:
error: variable-sized object 'tenorData' may not be initialized
Whereas using double tenorData[10] works.
Anyone know why?

In C++, variable length arrays are not legal. G++ allows this as an "extension" (because C allows it), so in G++ (without being -pedantic about following the C++ standard), you can do:
int n = 10;
double a[n]; // Legal in g++ (with extensions), illegal in proper C++
If you want a "variable length array" (better called a "dynamically sized array" in C++, since proper variable length arrays aren't allowed), you either have to dynamically allocate memory yourself:
int n = 10;
double* a = new double[n]; // Don't forget to delete [] a; when you're done!
Or, better yet, use a standard container:
int n = 10;
std::vector<double> a(n); // Don't forget to #include <vector>
If you still want a proper array, you can use a constant, not a variable, when creating it:
const int n = 10;
double a[n]; // now valid, since n isn't a variable (it's a compile time constant)
Similarly, if you want to get the size from a function in C++11, you can use a constexpr:
constexpr int n()
{
return 10;
}
double a[n()]; // n() is a compile time constant expression

Related

How to make an unknow size array global? [duplicate]

I am having the following issue with my code:
int n = 10;
double tenorData[n] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Returns the following error:
error: variable-sized object 'tenorData' may not be initialized
Whereas using double tenorData[10] works.
Anyone know why?
In C++, variable length arrays are not legal. G++ allows this as an "extension" (because C allows it), so in G++ (without being -pedantic about following the C++ standard), you can do:
int n = 10;
double a[n]; // Legal in g++ (with extensions), illegal in proper C++
If you want a "variable length array" (better called a "dynamically sized array" in C++, since proper variable length arrays aren't allowed), you either have to dynamically allocate memory yourself:
int n = 10;
double* a = new double[n]; // Don't forget to delete [] a; when you're done!
Or, better yet, use a standard container:
int n = 10;
std::vector<double> a(n); // Don't forget to #include <vector>
If you still want a proper array, you can use a constant, not a variable, when creating it:
const int n = 10;
double a[n]; // now valid, since n isn't a variable (it's a compile time constant)
Similarly, if you want to get the size from a function in C++11, you can use a constexpr:
constexpr int n()
{
return 10;
}
double a[n()]; // n() is a compile time constant expression

reference to an array in c++

Question is make an array of 10 integers that's fine
int array[10];
Now question is
how to make a reference to an array which I have declared above ?
I tried this
int &ra = a;
But it's giving me error...
Please provide me details about this error and how to make reference of an array.
int (&ra)[10] = a;
Alternatively, you can use a typedef to separate this into the type for "array of 10 ints" and having a reference there-to, as in:
typedef int int10[10];
int10& my_ref = a;
The problem with your int &ra = a; is that it tells the compiler to create a reference of type int that refers to an array of 10 ints... they're just not the same thing. Consider that sizeof(int) is a tenth of the size of an array of ten ints - they occupy different amounts of memory. What you've asked for with the reference's type could be satisfied by a particular integer, as in int& ra = a[0];.
I appreciate it's a bit confusing that int* p = a; is allowed - for compatibility with the less type-safe C, pointers can be used to access single elements or arrays, despite not preserving any information about the array size. That's one reason to prefer references - they add a little safety and functionality over pointers.
For examples of increased functionality, you can take sizeof my_ref and get the number of bytes in the int array (10 * sizeof(int)), whereas sizeof p would give you the size of the pointer (sizeof(int*)) and sizeof *p == sizeof(int). And you can have code like this that "captures" the array dimension for use within a function:
template <int N>
void f(int (&x)[N])
{
std::cout << "I know this array has " << N << " elements\n";
}
The reference to array will have type int (&a)[10].
int array[10];
int (&a)[10] = array;
Sometimes it might be useful to simplify things a little bit using typedef
typedef int (&ArrayRef)[10];
...
ArrayRef a = array;
This is a reference to an array of of ints of size 10:
int (&ra)[10];
so
int (&ra)[10] = a;
You can typedef the array type (the type should not be incomplete) as follow:
#define LEN 10
typedef int (array)[LEN];
int main(void)
{
array arr = {1, 2, 3, 4, 5}; //define int arr[10] = {1, 2, 3, 4, 5};
array arr2; //declare int arr[10];
array *arrptr = &arr; // pointer to array: int (*arrptr)[10] = &arr;
array &&arrvef; // declare rvalue reference to array of 10 ints
array &ref = arr; // define reference to arr: int (&ref)[10] = arr;
}

Aggregates in c++

In the following code why is that the two statements are illegal
const int i[] = { 1, 2, 3, 4 };
// float f[i[3]]; // Illegal
struct S { int i, j; };
const S s[] = { { 1, 2 }, { 3, 4 } };
//double d[s[1].j]; // Illegal
int main() {}
Why are they illegal? The textual definition is as follows which i didn't understand.
"In an array definition, the compiler must be able to generate code
that moves the stack pointer to accommodate the array. In both of the
illegal definitions above, the compiler complains because it cannot
find a constant expression in the array definition."
Thanks in advance.
Array sized need to be constant expressions. Try this:
constexpr int i[] = { 1, 2, 3, 4 };
float f[i[3]];
The constexpr keyword was introduced in C++11. Previous versions of C++ had no concept of such general constant expressions, and there was no equivalent concept.
Because C++ doesn't support variable-length arrays, and s[1].j is not a compile-time constant.
What that quote refers to is the fact that f and d are in automatic storage. The run-time will clean their memory automatically when they go out of scope. As such, it must know the size beforehand.
because d is static array, that means that it's size has to be know at compilation time.
Therefore you can't use non-const variables as size parameter.
But you can try
const int i = 3;
double d[i];
for example.

How to convert int to const int to assign array size on stack?

I am trying to allocate a fixed size on stack to an integer array
#include<iostream>
using namespace std;
int main(){
int n1 = 10;
const int N = const_cast<const int&>(n1);
//const int N = 10;
cout<<" N="<<N<<endl;
int foo[N];
return 0;
}
However, this gives an error on the last line where I am using N to define a fixed
error C2057: expected constant expression.
However, if I define N as const int N = 10, the code compiles just fine.
How should I typecast n1 to trat it as a const int?
I tried : const int N = const_cast<const int>(n1) but that gives error.
EDIT : I am using MS VC++ 2008 to compile this... with g++ it compiles fine.
How should I typecast n1 to treat it as a const int?
You cannot, not for this purpose.
The size of the array must be what is called an Integral Constant Expression (ICE). The value must be computable at compile-time. A const int (or other const-qualified integer-type object) can be used in an Integral Constant Expression only if it is itself initialized with an Integral Constant Expression.
A non-const object (like n1) cannot appear anywhere in an Integral Constant Expression.
Have you considered using std::vector<int>?
[Note--The cast is entirely unnecessary. Both of the following are both exactly the same:
const int N = n1;
const int N = const_cast<const int&>(n1);
--End Note]
Only fixed-size arrays can be allocated that way. Either allocate memory dynamically (int* foo = new int[N];) and delete it when you're done, or (preferably) use std::vector<int> instead.
(Edit: GCC accepts that as an extension, but it's not part of the C++ standard.)

initialize array size from another array value

#include<iostream>
using namespace std;
const int vals[] = {0, 1, 2, 3, 4};
int newArray[ vals[2] ]; //"error: array bound is not an integer constant"
int main(){
return vals[2];
}
//returns 2 if erroneous line is removed
Why doesn't this work?
Unfortunately you can't do that in standard C++ because vals[2] is not a constant expression! In the coming standard you would have constexpr(implemented in g++ 4.6) to request compile-time evaluation easily:
#include<iostream>
using namespace std;
constexpr int vals[] = {0, 1, 2, 3, 4};
int newArray[ vals[2] ]; // vals[2] is a constant expression now!
int main(){
return vals[2];
}
It's possible that the value of a const expression is not even known at compile time. For example, you can initialize a constant with something returned from a function, like
const int size = rand(); // random size
So it is not that constant as you might think
The C++ compiler can only allocate an array with a size known at compile time. If you want to allocated a variable size piece of memory, use the new operator.