Is there any difference in efficiency between (at global scope):
static const int MAX_CHAR (1024);
and
#define MAX_CHAR 1024
I'm wondering about both time and space efficiency. I can take the
address of the static const int, so surely it must take up space. The
define is 'just a number' so doesn't have to take up any space. Is
this right?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
studennett (5)
|
4/13/2006 6:52:27 AM |
|
"studennett" <studennett@hotmail.com> wrote in message
news:1144845365.832751.189250@j33g2000cwa.googlegroups.com...
: Is there any difference in efficiency between (at global scope):
:
: static const int MAX_CHAR (1024);
:
: and
:
: #define MAX_CHAR 1024
:
: I'm wondering about both time and space efficiency. I can take the
: address of the static const int, so surely it must take up space.
Space will have to be allocated *only* if you take the address.
[ I am not sure this is formally required by the standard,
but it is the expectation / typical implementation. ]
: The define is 'just a number' so doesn't have to take up any space.
: Is this right?
The key property of the #define is that it will escape any scoping
rules - i.e. you cannot encapsulate it within a namespace or class
scope.
If you are concerned about the constant taking space (you really
don't need to be), or face problems with legacy compilers, a much
better solution is to use an enum-constant:
enum {
max_char = 1024
};
hth-Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Ivan
|
4/14/2006 11:36:08 AM
|
|
Hello,
If it is possible, In C++ constant value is not stored in memory.
Therefore time space efficieny will be the same as for #define (for
this example). But const is safer...
(Word static mean that variable will be viewed only in file scope.)
Best regards
Mariusz
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
MariuszK
|
4/14/2006 11:43:54 AM
|
|
studennett wrote:
> Is there any difference in efficiency between (at global scope):
>
> static const int MAX_CHAR (1024);
>
> and
>
> #define MAX_CHAR 1024
>
> I'm wondering about both time and space efficiency. I can take the
> address of the static const int, so surely it must take up space. The
> define is 'just a number' so doesn't have to take up any space. Is
> this right?
No. You're assuming that it also takes up space if you / don't / take
its
address. However, with modern compilers it's precisely the act of
taking
its address that forces it to take up space. If you don't, the linker
will
see it as an unused symbol and remove it (except in debug mode, in
which case the compiler usually leaves it for the debuggers use.)
HTH,
Michiel Salters
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Michiel
|
4/14/2006 11:48:50 AM
|
|
studennett wrote:
> Is there any difference in efficiency between (at global scope):
> static const int MAX_CHAR (1024);
> and
> #define MAX_CHAR 1024
> I'm wondering about both time and space efficiency. I can
> take the address of the static const int, so surely it must
> take up space. The define is 'just a number' so doesn't have
> to take up any space. Is this right?
No. With any reasonable compiler, both should be exactly
equivalent when used in the same way.
If you take the address of the static const int, the compiler
probably will have to generate an instance of the variable. If
you need the address of the macro, you will have to define an
instance of the correct type too, so there is no difference
there either.
--
James Kanze GABI Software
Conseils en informatique orient�e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
kanze
|
4/14/2006 11:55:12 AM
|
|
studennett wrote:
> Is there any difference in efficiency between (at global scope):
> static const int MAX_CHAR (1024);
> and
> #define MAX_CHAR 1024
> I'm wondering about both time and space efficiency. I can
> take the address of the static const int, so surely it must
> take up space. The define is 'just a number' so doesn't have
> to take up any space. Is this right?
I just replied saying that there was no difference, but it
occurs to me that there is one case where there might be a
difference: when passing the value to a const reference (e.g. to
vector<int>::push_back). This is effectively the same thing as
taking its address -- it will force an instance of the static
const int; in the case of the #define, most of the compilers
I've seen will generate a temporary variable, initialize it, and
pass its address. So in this case, the static const int will
normally be faster and result in less space used.
--
James Kanze GABI Software
Conseils en informatique orient�e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
kanze
|
4/14/2006 11:56:07 AM
|
|
studennett wrote:
> Is there any difference in efficiency between (at global scope):
>
> static const int MAX_CHAR (1024);
>
> and
>
> #define MAX_CHAR 1024
>
> I'm wondering about both time and space efficiency. I can take the
> address of the static const int, so surely it must take up space. The
> define is 'just a number' so doesn't have to take up any space. Is
> this right?
Implementation dependent. The static const int must take up space IF
you take its address, yes. If you don't, it doesn't: you can't tell the
difference, so the "as if" rule applies.
It's much like function inlining - just because you can take the
address of a function, that doesn't mean the compiler can't inline it.
It just means that IF you take its address, the compiler ALSO has to
lay down a non-inlined copy to give you a pointer to.
cheers
Mike
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Mike
|
4/14/2006 11:59:19 AM
|
|
"studennett" <studennett@hotmail.com> writes:
> Is there any difference in efficiency between (at global scope):
>
> static const int MAX_CHAR (1024);
>
> and
>
> #define MAX_CHAR 1024
>
> I'm wondering about both time and space efficiency.
That former is more time efficient. Not execution time, but
developement time. Because variables are much better behaved than
macros.
> I can take the address of the static const int, so surely it must
> take up space.
It only has to take up space *if* you do something that requires it,
such as taking its address.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Thomas
|
4/14/2006 12:01:25 PM
|
|
Hello studennett,
> Is there any difference in efficiency between (at global scope):
>
> static const int MAX_CHAR (1024);
>
> and
>
> #define MAX_CHAR 1024
> I'm wondering about both time and space efficiency. I can take the
> address of the static const int, so surely it must take up space. The
> define is 'just a number' so doesn't have to take up any space. Is
> this right?
Almost. Yes, of course, simple number (define) is more fast to
process as
far as it doesn't include operations
with pointers. HOWEVER, most of today's compiler optimize first
option really
good and advantages you gain when
you aren't using #define are nothing compare with the advantages of
"normal"
consts.
Thanks!
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Aleksander
|
4/14/2006 1:37:12 PM
|
|
In article <1144845365.832751.189250
@j33g2000cwa.googlegroups.com>, studennett@hotmail.com
says...
> Is there any difference in efficiency between (at global scope):
>
> static const int MAX_CHAR (1024);
>
> and
>
> #define MAX_CHAR 1024
>
> I'm wondering about both time and space efficiency. I can take the
> address of the static const int, so surely it must take up space. The
> define is 'just a number' so doesn't have to take up any space. Is
> this right?
It may be right, but usually isn't. At least with most
compilers, the variable will take up space ONLY if you
take its address. There may be a few other things that
would force it to take up space, but in a typical case
the output code will be identical either way.
--
Later,
Jerry.
The universe is a figment of its own imagination.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Jerry
|
4/14/2006 1:37:43 PM
|
|
studennett wrote:
> Is there any difference in efficiency between (at global scope):
>
> static const int MAX_CHAR (1024);
>
> and
>
> #define MAX_CHAR 1024
>
> I'm wondering about both time and space efficiency. I can take the
> address of the static const int, so surely it must take up space. The
> define is 'just a number' so doesn't have to take up any space. Is
> this right?
If you use the address of the int then it must be allocated space. If
you dont take its address then the compiler can probably figure out
that it doesnt need to allocate space so you wont see it in the image
(I think the guarantee is even stronger inside a class). Of course with
the define you cant take its address.
Another alternative is an enum ...
regards
Andy Little
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
kwikius
|
4/14/2006 1:38:13 PM
|
|
studennett wrote:
> Is there any difference in efficiency between (at global scope):
>
> static const int MAX_CHAR (1024);
>
> and
>
> #define MAX_CHAR 1024
>
> I'm wondering about both time and space efficiency. I can take the
> address of the static const int, so surely it must take up space. The
> define is 'just a number' so doesn't have to take up any space. Is
> this right?
This is wrong. If the address of a constant is not used in the
program, a trivial linker optimization will remove it from the final
program.
One of the problems with '#define' is that once issued, it stays for
all the code, including the interfaces that are not yours. For example,
if the name MAX_CHAR appears in several places with different values,
it will be very difficult to use all the interfaces with their own
MAX_CHAR.
If you use a MAX_CHAR as a 'const int' and put it into an appropriate
namespace, you wouldn't depend on others not using the same name for
their constants.
BTW, '#define' is not C/C++, it's a preprocessor command. It makes
programs less readable. Whenever you want to use a '#define', think
about using a constant/inlined function/template instead. In most cases
there will be the same result, with a more structured program.
Michael
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Michael
|
4/14/2006 1:42:17 PM
|
|
> static const int MAX_CHAR (1024);
compiler can do more checks including type, scope. the MAX_CHAR will
be stored in data segment so it always occupies the space of memory but
only once under the scope.
> #define MAX_CHAR 1024
compiler doesn't check the type. The value could be embedded in some
machine instructions on some platforms, and not occupy extra memory. In
this kind of scenario, it is efficient. If MAX_CHAR is not a part of
machine instructions, it could duplicately occupy the memory space
under the scope of blocks or functions so it is possible to take up
more memory space than the first way.
I think that there is less difference in efficiency between them for
most cases but C++ likes the first way that perhaps takes up less
memory space.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
dan2online
|
4/14/2006 4:04:25 PM
|
|
In article <1144931041.913652.111920@z34g2000cwc.googlegroups.com>,
kanze <kanze@gabi-soft.fr> writes
>studennett wrote:
>> Is there any difference in efficiency between (at global scope):
>
>> static const int MAX_CHAR (1024);
>
>> and
>
>> #define MAX_CHAR 1024
>
>> I'm wondering about both time and space efficiency. I can
>> take the address of the static const int, so surely it must
>> take up space. The define is 'just a number' so doesn't have
>> to take up any space. Is this right?
>
>No. With any reasonable compiler, both should be exactly
>equivalent when used in the same way.
Except that the pre-processor version invades scopes. That is one reason
to use a different spelling for the two forms. Imagine that you had a
header file that had
#define MAX_CHAR 1024
and a .cpp file that had somewhere (possibly in a namespace)
static int const MAX_CHAR(512);
Any conceivable time saving by using the pre-processor macro would be
minute compared to the time wasted debugging the above code.
Do not use lower case letters in pre-processor identifiers and always
use at least one in names.
In general concern with this kind of micro-optimisation is misplaced,
the compiler will normally do an excellent job and except in rare cases,
any loss of time during the lifetime of the program as an executable
will be a small fraction of the programmer's time in attempting the
optimisation.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Francis
|
4/14/2006 4:51:47 PM
|
|
kwikius wrote:
> studennett wrote:
>> Is there any difference in efficiency between (at global scope):
>> static const int MAX_CHAR (1024);
>> and
>> #define MAX_CHAR 1024
>> I'm wondering about both time and space efficiency. I can
>> take the address of the static const int, so surely it must
>> take up space. The define is 'just a number' so doesn't have
>> to take up any space. Is this right?
> If you use the address of the int then it must be allocated
> space. If you dont take its address then the compiler can
> probably figure out that it doesnt need to allocate space so
> you wont see it in the image (I think the guarantee is even
> stronger inside a class). Of course with the define you cant
> take its address.
You can't explicitly take its address. You can still pass it as
a const reference, and the compiler will have to take its
address.
If you use the first form, you are guaranteed that the there
will be only one copy, since the language requires that the
address always be the same. If you use the #define, there's no
such guarantee, and you may end up with multiple copies, or
temporary copies which are reinitialized each time around.
The upshot of it all is that the clean solution is also the most
efficient one in terms of space and runtime.
--
James Kanze kanze.james@neuf.fr
Conseils en informatique orient�e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
James
|
4/15/2006 12:10:49 PM
|
|
Francis Glassborow wrote:
> In article <1144931041.913652.111920@z34g2000cwc.googlegroups.com>,
> kanze <kanze@gabi-soft.fr> writes
>> studennett wrote:
>>> Is there any difference in efficiency between (at global scope):
>>> static const int MAX_CHAR (1024);
>>> and
>>> #define MAX_CHAR 1024
>>> I'm wondering about both time and space efficiency. I can
>>> take the address of the static const int, so surely it must
>>> take up space. The define is 'just a number' so doesn't have
>>> to take up any space. Is this right?
>> No. With any reasonable compiler, both should be exactly
>> equivalent when used in the same way.
> Except that the pre-processor version invades scopes.
This may surprise you, but I'm aware of that:-). I sort of
mis-phrased my answer -- what I meant to say is that with any
reasonable compiler, there will be no difference in the
generated code.
Except that immediately after posting, I realized that that was
wrong. Because in practice, the compiler often has to generate
an address for the constant: in the const int form, that is no
problem but in the #define form, the compiler must do more work.
The result is that the #define form will probably result in
larger and slower code. (Of course, I can't image the
difference being significant in any real application.)
> That is one reason to use a different spelling for the two
> forms. Imagine that you had a header file that had
> #define MAX_CHAR 1024
>
> and a .cpp file that had somewhere (possibly in a namespace)
> static int const MAX_CHAR(512);
> Any conceivable time saving by using the pre-processor macro
> would be minute compared to the time wasted debugging the
> above code.
What time wasted debugging it. I'd just throw it out and start
over:-).
> Do not use lower case letters in pre-processor identifiers and
> always use at least one in names.
For example. (It's as good a rule as any, and you do need some
rule. I also insist that preprocessor names be at least three
characters long, to avoid conflicts with simple one letter
typenames.)
> In general concern with this kind of micro-optimisation is
> misplaced, the compiler will normally do an excellent job and
> except in rare cases, any loss of time during the lifetime of
> the program as an executable will be a small fraction of the
> programmer's time in attempting the optimisation.
I really should have cut the above, but it is so accurate that
it can't be repeated too often.
--
James Kanze kanze.james@neuf.fr
Conseils en informatique orient�e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
James
|
4/15/2006 8:09:11 PM
|
|
Michael Tiomkin wrote:
> BTW, '#define' is not C/C++, it's a preprocessor command. It makes
> programs less readable.
A technical nit: #define is a preprocessor directive (rather
than a "command") as it is part of both the C and the C++
programming languages as defined by their respective standards.
(That said, there is a useful distinction between those parts
of the language that are implemented in "the preprocessor" and
those which happen after conversion of preprocessor tokens to
"real" tokens. It's just that both are part of C++, and of C.)
> Whenever you want to use a '#define', think
> about using a constant/inlined function/template instead. In most cases
> there will be the same result, with a more structured program.
>
> Michael
True; good uses for the preprocessor are reasonably rare,
particularly if we ignore #ifndef guards around header files.
-- James
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
James
|
4/15/2006 8:25:24 PM
|
|
James Kanze wrote:
> kwikius wrote:
> > If you use the address of the int then it must be allocated
> > space. If you dont take its address then the compiler can
> > probably figure out that it doesnt need to allocate space so
> > you wont see it in the image (I think the guarantee is even
> > stronger inside a class). Of course with the define you cant
> > take its address.
>
> You can't explicitly take its address. You can still pass it as
> a const reference, and the compiler will have to take its
> address.
>
> If you use the first form, you are guaranteed that the there
> will be only one copy, since the language requires that the
> address always be the same. If you use the #define, there's no
> such guarantee, and you may end up with multiple copies, or
> temporary copies which are reinitialized each time around.
>
> The upshot of it all is that the clean solution is also the most
> efficient one in terms of space and runtime.
Actually I remember that use of static const ints inside classes caused
problems and so I switched to using enums. Below is an example that
shows the problem in gcc 4.0( and probably other gcc versions) when
S::value is defined as an static const int , but disappears if its
defined as an enum. Note that the code links fine either way in VC7.1,
the other compiler tested. I have no idea who is correct.
#include <iostream>
struct S{
#if(1)
static int const value =1;
#else
enum{value =1};
#endif
};
int f( const int & n){return n;}
int main()
{
int n = f(S::value);
std::cout << n << '\n';
}
When S::value is a static const int the gcc linker complains:
test.o:test.cpp:(.text+0x27): undefined reference to `S::value'
collect2: ld returned 1 exit status
regards
Andy Little
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
kwikius
|
4/15/2006 8:36:58 PM
|
|
kwikius wrote:
>
> #include <iostream>
> struct S{
> #if(1)
> static int const value =1;
> #else
> enum{value =1};
> #endif
> };
>
> int f( const int & n){return n;}
>
> int main()
> {
> int n = f(S::value);
> std::cout << n << '\n';
> }
>
> When S::value is a static const int the gcc linker complains:
>
> test.o:test.cpp:(.text+0x27): undefined reference to `S::value'
> collect2: ld returned 1 exit status
>
I am not quite sure about the reason, but I noticed that if you
initialize your constant outside the class:
const int S::value = 1 ;
then the error gcc does not complain anymore...
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Vincent
|
4/17/2006 10:58:37 AM
|
|
kwikius wrote:
> James Kanze wrote:
>> kwikius wrote:
>> > If you use the address of the int then it must be
>> > allocated space. If you dont take its address then the
>> > compiler can probably figure out that it doesnt need to
>> > allocate space so you wont see it in the image (I think
>> > the guarantee is even stronger inside a class). Of course
>> > with the define you cant take its address.
>> You can't explicitly take its address. You can still pass it
>> as a const reference, and the compiler will have to take its
>> address.
>> If you use the first form, you are guaranteed that the there
>> will be only one copy, since the language requires that the
>> address always be the same. If you use the #define, there's
>> no such guarantee, and you may end up with multiple copies,
>> or temporary copies which are reinitialized each time around.
>> The upshot of it all is that the clean solution is also the
>> most efficient one in terms of space and runtime.
> Actually I remember that use of static const ints inside
> classes caused problems and so I switched to using enums.
> Below is an example that shows the problem in gcc 4.0( and
> probably other gcc versions) when S::value is defined as an
> static const int , but disappears if its defined as an enum.
> Note that the code links fine either way in VC7.1, the other
> compiler tested. I have no idea who is correct.
G++. But I think that the error is in fact undefined behavior,
so no compiler diagnostic is involved.
> #include <iostream>
> struct S{
> #if(1)
> static int const value =1;
Note that this is still a declaration, even though an
initialization value is present. Formally, a definition is
required.
> #else
> enum{value =1};
> #endif
> };
> int f( const int & n){return n;}
And to call this function, the compiler will have to take the
address of the object.
> int main()
> {
> int n = f(S::value);
> std::cout << n << '\n';
> }
> When S::value is a static const int the gcc linker complains:
> test.o:test.cpp:(.text+0x27): undefined reference to
> `S::value' collect2: ld returned 1 exit status
Which is perfectly acceptable. (In the case of undefined
behavior, anything the compiler does is "acceptable". Although
from a quality of implementation point of view -- I would expect
either a diagnostic, at the latest at link time, or that the
code work.)
Try defining the variable in one (and only one) translation
unit, e.g.:
int const S::value ;
(Note that since the declaration has an initialization value, no
initialization should be given here.)
--
James Kanze kanze.james@neuf.fr
Conseils en informatique orient�e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
James
|
4/17/2006 8:39:56 PM
|
|
"Vincent Poinot" <vincent.use-my-last-name-here@wanadoo.fr> skrev i
meddelandet news:44421b6e$0$20184$8fcfb975@news.wanadoo.fr...
> kwikius wrote:
>>
>> #include <iostream>
>> struct S{
>> #if(1)
>> static int const value =1;
>> #else
>> enum{value =1};
>> #endif
>> };
>>
>> int f( const int & n){return n;}
>>
>> int main()
>> {
>> int n = f(S::value);
>> std::cout << n << '\n';
>> }
>>
>> When S::value is a static const int the gcc linker complains:
>>
>> test.o:test.cpp:(.text+0x27): undefined reference to `S::value'
>> collect2: ld returned 1 exit status
>>
To pass by reference, you need an object to pass. As it is just
declared, but never defined, there is no object.
Now, you might wonder why you want to pass a constant by reference
anyway, but that is another question. :-)
> I am not quite sure about the reason, but I noticed that if you
> initialize your constant outside the class:
>
> const int S::value = 1 ;
There you have your object, and the linker will find it.
Bo Persson
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Bo
|
4/17/2006 8:41:53 PM
|
|
Vincent Poinot wrote:
> kwikius wrote:
> >
> > #include <iostream>
> > struct S{
> > #if(1)
> > static int const value =1;
> > #else
> > enum{value =1};
> > #endif
> > };
> >
> > int f( const int & n){return n;}
> >
> > int main()
> > {
> > int n = f(S::value);
> > std::cout << n << '\n';
> > }
> >
> > When S::value is a static const int the gcc linker complains:
> >
> > test.o:test.cpp:(.text+0x27): undefined reference to `S::value'
> > collect2: ld returned 1 exit status
> >
> I am not quite sure about the reason, but I noticed that if you
> initialize your constant outside the class:
>
> const int S::value = 1 ;
>
> then the error gcc does not complain anymore...
The problem is in order for function f()'s const reference parameter to
bind to S::value, S::value must have allocated storage. When passing an
enum instead of S::value the compiler allocates the necessary storage
itself, in the form of a temporary which is then bound to the const
reference.
A better solution than allocating storage for S::value is to change the
declaration of f() to accept an int parameter by value. An int
parameter passed by value is certain to be more efficient than passing
a const reference to an int. There is in fact simply no reason for f to
be declared as it is. And without the const reference parameter, f()
will accept S::value as a parameter without requiring that it have any
allocated storage.
Greg
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Greg
|
4/17/2006 8:46:40 PM
|
|
Vincent Poinot wrote:
> kwikius wrote:
> >
> > #include <iostream>
> > struct S{
> > #if(1)
> > static int const value =1;
> > #else
> > enum{value =1};
> > #endif
> > };
> >
> > int f( const int & n){return n;}
> >
> > int main()
> > {
> > int n = f(S::value);
> > std::cout << n << '\n';
> > }
> >
> > When S::value is a static const int the gcc linker complains:
> >
> > test.o:test.cpp:(.text+0x27): undefined reference to `S::value'
> > collect2: ld returned 1 exit status
> >
> I am not quite sure about the reason, but I noticed that if you
> initialize your constant outside the class:
>
> const int S::value = 1 ;
>
> then the error gcc does not complain anymore...
I think you'd get an error with that, because you have defined the
value of value twice. It should be just const int S::value;
The language does actually require that you do this. However, I have
noticed that several compilers / linkers seem to work quite happily if
you don't do this (actually, it was a nasty shock when we used one that
required you to do this - quite a lot of code broke).
It seems to me that this restriction could be withdrawn, although it
would require facilities in the linker of the sort that are needed for
template instantiation. The compiler could generate an instance of
S::value every time S::value was potentially used, and the linker could
then throw away all but one.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
ThosRTanner
|
4/17/2006 8:51:04 PM
|
|
Greg Herlihy wrote:
> Vincent Poinot wrote:
>> kwikius wrote:
>>> #include <iostream>
>>> struct S{
>>> #if(1)
>>> static int const value =1;
>>> #else
>>> enum{value =1};
>>> #endif
>>> };
>>> int f( const int & n){return n;}
[...]
> A better solution than allocating storage for S::value is to
> change the declaration of f() to accept an int parameter by
> value. An int parameter passed by value is certain to be more
> efficient than passing a const reference to an int. There is
> in fact simply no reason for f to be declared as it is.
This is true, but then, it isn't very reasonable to call a
function f, either. I would imagine that the posted code is a
simplification of the actual code, and the f is just a place
holder for some more complicated function. Say
std::vector<int>::push_back() (which does take a const int&).
> And without the const reference parameter, f() will accept
> S::value as a parameter without requiring that it have any
> allocated storage.
Typically, in any case. I"m not sure what the standard requires
here -- whether it is required to work, or whether it is
undefined behavior which in practice always works. It really
doesn't matter -- an integral constant that can't be
push_back'ed into a vector<int> is not a very user friendly
beast, and I would make it a rule to always provide the
definition.
--
James Kanze kanze.james@neuf.fr
Conseils en informatique orient�e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
James
|
4/18/2006 11:17:18 AM
|
|
James Kanze wrote:
> kwikius wrote:
> > When S::value is a static const int the gcc linker complains:
>
> > test.o:test.cpp:(.text+0x27): undefined reference to
> > `S::value' collect2: ld returned 1 exit status
>
> Which is perfectly acceptable. (In the case of undefined
> behavior, anything the compiler does is "acceptable". Although
> from a quality of implementation point of view -- I would expect
> either a diagnostic, at the latest at link time, or that the
> code work.)
>
> Try defining the variable in one (and only one) translation
> unit, e.g.:
>
> int const S::value ;
>
> (Note that since the declaration has an initialization value, no
> initialization should be given here.)
Ah Ha! ...That does indeed solve the problem and works on both
compilers, however the problem occurred in what was meant to be a
header only library and therefore that solution would have an impact in
terms of ease of use of the library. Note that the enum solution works
very nicely in this case, but does have its own problems, requiring for
example, to be explicitly static cast to an int ( in gcc ), to prevent
errors in some compile time math operations, the exact circumstances of
which I now forget ( struct1::enuma < struct2::enumb ??).
regards
Andy Little
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
kwikius
|
4/18/2006 11:32:12 PM
|
|
Greg Herlihy wrote:
> > kwikius wrote:
> > > int f( const int & n){return n;}
> A better solution than allocating storage for S::value is to change the
> declaration of f() to accept an int parameter by value. An int
> parameter passed by value is certain to be more efficient than passing
> a const reference to an int. There is in fact simply no reason for f to
> be declared as it is. And without the const reference parameter, f()
> will accept S::value as a parameter without requiring that it have any
> allocated storage.
FWIW The problem was brought up by a user of my pqs library
http://tinyurl.com/7m5l8 .(Currently in the review queue hoping to
become part of the boost libraries http://www.boost.org ) IOW I had no
control of how the function was defined... maybe nor did he.
regards
Andy Little
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
kwikius
|
4/18/2006 11:32:34 PM
|
|
kwikius wrote:
> James Kanze wrote:
> > kwikius wrote:
>
> > > If you use the address of the int then it must be allocated
> > > space. If you dont take its address then the compiler can
> > > probably figure out that it doesnt need to allocate space so
> > > you wont see it in the image (I think the guarantee is even
> > > stronger inside a class). Of course with the define you cant
> > > take its address.
> >
> > You can't explicitly take its address. You can still pass it as
> > a const reference, and the compiler will have to take its
> > address.
> >
> > If you use the first form, you are guaranteed that the there
> > will be only one copy, since the language requires that the
> > address always be the same. If you use the #define, there's no
> > such guarantee, and you may end up with multiple copies, or
> > temporary copies which are reinitialized each time around.
> >
> > The upshot of it all is that the clean solution is also the most
> > efficient one in terms of space and runtime.
>
> Actually I remember that use of static const ints inside classes caused
> problems and so I switched to using enums. Below is an example that
> shows the problem in gcc 4.0( and probably other gcc versions) when
> S::value is defined as an static const int , but disappears if its
> defined as an enum. Note that the code links fine either way in VC7.1,
> the other compiler tested. I have no idea who is correct.
>
> #include <iostream>
> struct S{
> #if(1)
> static int const value =1;
> #else
> enum{value =1};
> #endif
> };
>
> int f( const int & n){return n;}
>
> int main()
> {
> int n = f(S::value);
> std::cout << n << '\n';
> }
>
> When S::value is a static const int the gcc linker complains:
>
> test.o:test.cpp:(.text+0x27): undefined reference to `S::value'
> collect2: ld returned 1 exit status
>
> regards
> Andy Little
I tried your code in comeau, one of the more standard compliant
compilers, it compiled the snippet without any problem in strict error
mode. But since comeau does not link (and some of the intricacies in
this program only arises during link time), there is still question
unanswered.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Fei
|
5/2/2006 10:38:25 AM
|
|
|
26 Replies
115 Views
(page loaded in 0.2 seconds)
Similiar Articles: const member functions in classes derived from templates. - comp ...Static const integral data members can ... boost.variant and its efficiency - comp.lang.c++.moderated ... const ... What is Difference between const int i and int const i ... What is Difference between const int i and int const i - comp.lang ...... what is being declared const in a ... use a simple rule, place the const ... const integral data members can be initialized? - comp.lang ... What is Difference between const ... SOLUTION: compile time array size using type only - comp.lang.c++ ...Q: What is the most annoying thing on ... that I don't need a constant integral expression. So my code uses the simple ... Static const integral data members can be ... nitializing a static vector <> of integers (this static vector... Static data member are initialized in their definition ... on vector is overloaded and is _not_ as simple as C ... Static const integral data members can be initialized ... Why no std::back_insert_iterator::value_type? - comp.lang.c++ ...I.e. what is OutIter::value_type ... the static_cast is better than simple ... neither reinterpret_cast nor const_cast will apply in those cases. Ditto for integral ... enum and operator++ - comp.lang.c++Dear all I am struggling with a problem that's simple ... There's no undefined behavior given his definition of ... Normally, an operator++ takes a non-const reference ... "Moderated" List??? - comp.lang.asm.x86... forum for discussion of coding techniques and efficiency ... name list - comp.soft-sys.matlab Hello, I have a simple ... What Is a Moderated Mailing List? | eHow.com Moderated ... Converting number to std::string ("itoa()" ) - comp.lang.c++ ...... which starts with the return type (char const *). To what is the ... in the standard library that would produce simple ... (I once wrote a function which would convert integral ... Base64 Encoding Library - comp.unix.programmer... than it is needed to write simple base64 ... include <string.h> #endif #define Assert(Cond) if (!(Cond)) abort() static const char ... on the right) to form an integral ... Dos and don'ts in C++ unit testing? - comp.lang.c++.moderated ...For integration and systems testing, I tend to use a ... In debuggers, it's easier to view the values of simple ... Lots of what is said about C# and Java testing applies ... improve strlen - comp.lang.asm.x86int xstrlen(const char* text) { const char* p = text ... replied to, maybe you should afterall read what is being ... has a bad reputation in terms of programmer efficiency ... Should I use C++ or Java for Numeric Intensive Calculations - comp ...Matlab has a simple syntax especially suited to ... If you need integration or fourier transforms, then a math ... of templates and overloading saves on time, efficiency ... integer overflow in atoi - comp.lang.cSo it's a lot easier to implement long atol (const ... common case to fall out fast (if you need the efficiency ... What is better to convert a string to an integer value. Surface normals? - comp.graphics.api.opengl... is that you put the vertex arrays into object, define ... computing normals for a complex geometry is simple ... Flux Integral: Numerical Integration of Vector Field ... Nonlinear curve fit fails to converge - comp.soft-sys.matlab ...... final values are unknown but are expected to be const... ... ends too soon after the switch to make this simple ... the datasets to know that this is a pretty safe definition ... C syntax - Wikipedia, the free encyclopediaThe C language represents numbers in three forms: integral ... The type qualifier const indicates that the value of an ... memory that is allocated to it can be limited to what is ... C++ classes - Wikipedia, the free encyclopediaClasses define types of data structures and the ... presentation (although this could decrease efficiency of ... members that can occupy less storage than an integral ... 7/16/2012 9:22:40 PM
|