A program like this can even be compiled! I feel confused.

we all know const object need to initialized when defined. But it can be initialized by a variable is really amazing!

We also know that an array can be defined only if the dimension is known when compiling, but the following program really passed the compilation, only with a warning that "i is used while uninitialized."

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

int main() {
	int i, j=1;
	const int ci=i;
	const int cj=j;
	//const int ck;
	int a[i];
	int b[j];
	int ac[ci];
	int bc[cj];
	cout << ci<<endl<<cj << endl; 
        cout << a[0]<<b[0]<<ac[0]<<bc[0]<<endl;
	return 0;
}


who can explain this? Is this g++ 's special improvement or the c++ standard?
I mean the compiler really don't care about the value is a constant or not, it only care about it is declared as const or not.
Last edited on
I won't look up and quote the standard to you, but it is acceptable to initialize a constant value with a non-constant variable in local blocks.

(At file scope, and for static local objects, the initializer must also be a compile-time constant. There are ways around that, though, if you know what you are doing, but you must be sure to explicitly mark such objects as volatile so that the compiler will not try to optimize it the wrong way.)

TL;DR
The constant value is constant from the point of declaration/initialization. The initializer itself need not be constant.
closed account (G30GNwbp)
These are the flags I gave the compiler:
g++ -std=c++11 -Wall -Wextra -pedantic temp.cpp

And these are the warnings I get--they seem pretty obvious to me that there is going to be problems:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
temp.cpp: In function 'int main()':
temp.cpp:9:9: warning: ISO C++ forbids variable length array 'a' [-Wvla]
  int a[i];
         ^
temp.cpp:10:9: warning: ISO C++ forbids variable length array 'b' [-Wvla]
  int b[j];
         ^
temp.cpp:11:11: warning: ISO C++ forbids variable length array 'ac' [-Wvla]
  int ac[ci];
           ^
temp.cpp:12:11: warning: ISO C++ forbids variable length array 'bc' [-Wvla]
  int bc[cj];
           ^
temp.cpp:6:15: warning: 'i' is used uninitialized in this function [-Wuninitialized]
  const int ci=i;
               ^
Sorry, I only answered 1/3 of your question.

You never give i a value -- hence when you use it, the compiler complains that it is not initialized. It's value could be anything when your program runs.

The variable-length array problem is because the array size has to be known at the time of compilation. i and j are automatically invalid, but so are ci and cj -- because their initializer is not a compile-time constant.

Hence, it is a "variable length array" -- the length of the array is not known at compile time.


IIRC, C++14 will support VLAs. Until then, you must compile such things with compiler-specific extensions.

Or, just do it the standard C++ way and use a vector.

1
2
3
4
  vector <int> ac( ci );

  if (ci > 0)
    cout << ac[0] << endl;

Or dynamic allocation and all the attendant boilerplate:

1
2
3
4
5
6
7
8
9
10
11
12
  int* ac = new int[ ci ];
  try
    {
    if (ci > 0)
      cout << ac[0] << endl;
    }
  catch (...)
    {
    delete [] ac;
    throw;
    }
  delete [] ac;

Hope this helps.
@northfly

Please copy/paste the command line used for compile and build your programs.I'm using the following:

g++ -Wall -Wextra -std=c++11 -pedantic -pedantic-errors -o qaz qaz.cpp

and here's the message for your code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
qaz.cpp: In function ‘int main()’:
qaz.cpp:9:9: error: ISO C++ forbids variable length array ‘a’ [-Wvla]
  int a[i];
         ^
qaz.cpp:10:9: error: ISO C++ forbids variable length array ‘b’ [-Wvla]
  int b[j];
         ^
qaz.cpp:11:11: error: ISO C++ forbids variable length array ‘ac’ [-Wvla]
  int ac[ci];
           ^
qaz.cpp:12:11: error: ISO C++ forbids variable length array ‘bc’ [-Wvla]
  int bc[cj];
           ^
Compilation failed.
we all know const object need to initialized when defined. But it can be initialized by a variable is really amazing!

const has double meaning: it always means the object is read-only, but it also can mean the value is known at compile time. In your case, ci and cj are read-only objects, whose values are not compile-time constants.

This was disambiguated in C++11 with the new keyword constexpr, which always means compile-time constant.

and yes, only constants that are known at compile time can be used as array bounds (this was going to be changed in C++14, but it didn't happen. Might happen in C++17). Your compiler is using a non-standard language extension.
Thanks a lot, Guys!
I think I am more clear now.
Topic archived. No new replies allowed.