Const vars vs. defines


P

Pelle Beckman

Hi,

I saw this code in an earlier post
(not that there's anything wrong with it)

#include <iostream>
using std::cout;

const int hour = 3600;
const int min = 60;

class Time
{
int m_t; // member seconds
public:
Time(int t) : m_t(t)
{
...


What's up with Cpp-stuff like this?
What's so much more practical with consts vs. #defines?
It uses unnecessary space, and the typical use (at least for me)
are _simple_ constants like SCREEN_WRES, SECS_IN_HOUR, etc.

Yes, there are issues when formatting, data types, etc. can
can get nasty with defines, but do professional programmers like _you_
ever have problems with defines?
I'm actually wondering.

-- Pelle
 
Ad

Advertisements

J

John Carson

Pelle Beckman said:
Hi,

I saw this code in an earlier post
(not that there's anything wrong with it)

#include <iostream>
using std::cout;

const int hour = 3600;
const int min = 60;

class Time
{
int m_t; // member seconds
public:
Time(int t) : m_t(t)
{
...


What's up with Cpp-stuff like this?
What's so much more practical with consts vs. #defines?
It uses unnecessary space, and the typical use (at least for me)
are _simple_ constants like SCREEN_WRES, SECS_IN_HOUR, etc.

Yes, there are issues when formatting, data types, etc. can
can get nasty with defines, but do professional programmers like _you_
ever have problems with defines?
I'm actually wondering.

-- Pelle


One advantage of the const int version is that it respects scopes. #defines
don't.
 
P

Pelle Beckman

John Carson skrev:
One advantage of the const int version is that it respects scopes.
#defines don't.
true, and very smart.
I've never thought of that.
 
K

Karl Heinz Buchegger

John said:
One advantage of the const int version is that it respects scopes. #defines
don't.

Another thing is that may debugger knows about the constants because they
are ordinary constant variabels. However my debugger knows nothing
about macros.
 
Ad

Advertisements

K

Kanenas

Hi,
Hello.
[...]
What's so much more practical with consts vs. #defines?
It uses unnecessary space, and the typical use (at least for me)
are _simple_ constants like SCREEN_WRES, SECS_IN_HOUR, etc.
You're question is restricted to simple types, so we don't need to
bring const aggregate types into this.

Compilers can optimize out 'const' variables by replacing them with
their value, which removes the need to store the value in any object
file. A stripped binary will incur no penalty for the use of a const
over a macro in the source. A variable which has been optimized out
in this manner may no longer be visible to a debugger; at the very
least, its value won't, but the value can be determined by inspecting
the source (see difference 2 below for more on this).

Even without the optimization, the space penalty for simple constants
is negligible, unless you're working on an embedded system. Even with
64 bit ints, 128 const ints will only consume 1 KB to store their
values.

Most differences between the two is the result of the fact that const
variables respect C++ syntax and semantics while macros ignore it
(both John Carson's point about scopes and the points below are
consequences of this). For example,

1) const variables have an implicit type; macro names do not (though a
macro's value may have a type). Whether that works for you or against
you depends on context.

2) Macros can cause problems with or reduce the efficacy of various
programming tools, including documentation generators and other
literate programming tools, cross reference tools and syntax checkers.
Karl Heinz Buchegger already mentioned debuggers.

2) This point is more about the problems of #undef than macro
constants. If you've seen a macro defined in one place and used
somewhere else, and the locations are in different files or there are
intervening includes, you can't really know the value of the macro
when used. If you see the definition of a const variable and see it
used somewhere else, you can be almost certain of its value. This is
because you can only cast away the const-ness of pointers and
references, which means more hoops to jump through to assign to a
non-pointer and non-ref const, whereas you can easily undefine and
redefine a macro. Redefining a macro will never be a problem if all
programmers involved are perfect, but in all other cases is a
potential source of bugs. If i is a global const int,
"*(const_cast<int*>(&i))=1" will compile but you may get a segfault
when the assignment is executed. Redefining a macro is more likely to
compile and run without obvious errors, but you may get unexpected and
hard to debug behavior. Whether any of that works for you or against
you depends on context.

Kanenas
 

Top