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
I just started learning C++. I learned the easy way of declaring arrays and now I'm confused about the usage of
int* foo = new int[n];
and how it is different from
int foo [n];
I tried testing with code but couldn't find any difference. I read from sources that using "new" requires me to manually de-allocate the memory after I don't need it anymore. In that case, there is no advantage in using "new" or dynamic memory allocation at all. Am I missing something here?
I tried running this:
#include <iostream>
int main() {
int n;
std::cout << "array size" ;
std::cin >> n ;
std::cout << n ;
int foo [n]; //line A
// int* foo = new int[n]; //line B
foo[6] = 30;
std::cout<<foo[6]<<std::endl;
}
Commenting out line B to run line A, or vice versa, gave the exact same result.
There are several ways these are different. First, let's talk about this one:
int n = 10;
int array[n];
This is not part of the ANSI C++ standard and may not be supported by all compilers. You shouldn't count on it. Imagine this code:
int n = 10;
int array[n];
n = 20;
How big is array?
Now, this is the way you can do it (but it's still problematic):
int n = 10;
int * array = new int[n];
Now, that is legal. But you have to remember later to:
delete [] array;
array = nullptr;
Now, there are two other differences. The first one allocates space on the stack. The second allocates space on the heap, and it's persistent until you delete it (give it back). So the second one could return the array from a function, but the first one can't, as it disappears when the function exits.
HOWEVER... You are strongly, strongly discouraged from doing either. You should instead use a container class.
#include <array>
std::array<int, n> array;
The advantages of this:
It's standard and you can count on it
You don't have to remember to free it
It gives you range checking
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
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.
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.)
#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.