f(int i) declaration, f(const int i) definition?

D

dean

We were working through one of Sutter's books this lunch time, and it
came about that you can put a function:

void f(int i); // in the header file

and

void f(const int i) {} // as the definition.

My question is: is that correct? Isn't the type const int different
from just int? I presume that inside function f, one could not change
i if it's marked as const in the declaration, even if its marked so
ONLY in the declaration.

-Thanks for reading!
-Dean
 
J

Jack Klein

We were working through one of Sutter's books this lunch time, and it
came about that you can put a function:

void f(int i); // in the header file

and

void f(const int i) {} // as the definition.

My question is: is that correct? Isn't the type const int different
from just int? I presume that inside function f, one could not change
i if it's marked as const in the declaration, even if its marked so
ONLY in the declaration.

A top-level const qualifier has no meaning on a function parameter. An
int, or any other object type, is passed by value. The int object
that f() receives is its very own copy, so whatever f() does to its
'i' has no effect on the caller.

The const qualifier in the definition will prevent f() from changing
its 'i'.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
C

Chris Thomasson

Jack Klein said:
A top-level const qualifier has no meaning on a function parameter. An
int, or any other object type, is passed by value. The int object
that f() receives is its very own copy, so whatever f() does to its
'i' has no effect on the caller.

The const qualifier in the definition will prevent f() from changing
its 'i'.
[...]

FWIW, I find that useful in C; basically, to mimic the 'this' pointer in
C++. Something like:
_____________________________________________________________
typedef struct foo_s foo;

struct foo_s {
[...];
};

void
foo_do_something(
foo* const _this,
) {
[...]
}
_____________________________________________________________



I am not allowed to mess with the '_this' parameter in the definition of the
'foo_do_something()' function.
 
C

Chris Thomasson

_____________________________________________________________
typedef struct foo_s foo;

struct foo_s {
[...];
};

void
foo_do_something(
foo* const _this,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

of course that comma is not supposed to be there!

ARGH!

) {
[...]
}
_____________________________________________________________
 
D

dean

A top-level const qualifier has no meaning on a function parameter. An
int, or any other object type, is passed by value.  The int object
that f() receives is its very own copy, so whatever f() does to its
'i' has no effect on the caller.

The const qualifier in the definition will prevent f() from changing
its 'i'.

Yes, I can see that, I was just questioning why the definition is
allowed to change from the declaration. The writer of the function may
want to indicate that the parameter won't be changed throughout the
function body, for example if its an index into an array.
 
P

ppi

Yes, I can see that, I was just questioning why the definition is
allowed to change from the declaration. The writer of the function may
want to indicate that the parameter won't be changed throughout the
function body, for example if its an index into an array.

As J.Klein said, top-level const qualifier has no meaning on the
function parameter:
you can rephrase that by saying that f( int a ) and f( const int a )
have the same signature from the compiler point of view.
so When you declare:
int loop( int a );
int loop( const int a );

for the compiler this is the same declaration. But if you try:
int loop( int a )
{
return a+1;
}

int loop( const int a )
{
return a+2;
}

Boom ! This is flagged as defining twice the same function.

From my gcc compiler:

int loop( int a );
int loop( const int a );

int loop( int a )
{
return a+1;
}

int loop( const int a )
{
return a+2;
}


c++ -c loop.cpp
loop.cpp: In function 'int loop(int)':
loop.cpp:9: error: redefinition of 'int loop(int)'
loop.cpp:4: error: 'int loop(int)' previously defined here

c++ --version gives me:
c++ (GCC) 4.2.3

So yes for functions passing parameters by value you may end up by
defining a function with different function bodies (const / non const
index inside the function).
Note that as previously said, the caller does not care what you do
inside the function since its parameter is not changed.
But you, the implementor, you have more freedom in defining the
content of the function.

-- paulo
 
A

Andrey Tarasevich

dean said:
We were working through one of Sutter's books this lunch time, and it
came about that you can put a function:

void f(int i); // in the header file

and

void f(const int i) {} // as the definition.

My question is: is that correct? Isn't the type const int different
from just int?

Well, there's no definitive answer to that question within the C++98
language specification. It is not clear on this, which is recognized in
defect report #140

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#140

According to the original intent, function declarations should be
matched to each other in accordance with their adjusted parameter lists,
i.e. after (not before) all array and function types are replaced with
corresponding pointer types and all top-level cv-qualifiers are removed.
The original version of the standard failed to address this
"before/after" ambiguity.

I don't know when the changes suggested by DR#140 were incorporated into
the document, but I can see them in N2461.

The compilers followed the intended approach from the very beginning, so
you can use it safely.
 
A

Andrey Tarasevich

Jack said:
...
A top-level const qualifier has no meaning on a function parameter. An
int, or any other object type, is passed by value. The int object
that f() receives is its very own copy, so whatever f() does to its
'i' has no effect on the caller.
...

The fact that the local parameter value doesn't change can still be quite useful
from the caller's point of view. While it is true that at the C++ language level
this to have ho effect on the caller, it still can be used to generate better
caller code. In traditional implementation the caller prepares the arguments in
a special "argument area" (stack frame, for example), which is later directly
accessed by the function as its local parameters. If some parameter is declared
as 'const', the caller can be sure that it is not changed by the function and
therefore can be reused for the several consecutive function calls.

For example,

void foo(const int i, int j) {
...
}

...

int a = 5;
for (int b = 0; b < 1000; ++b)
foo(a, b);

In this the compiler can prepare the 'i' parameter for the future 'foo' calls
only once, before the cycle begins, instead of re-initializing it on every
iteration.

Unfortunately, the declaration matching rules in C/C++ are to loose to use this
kind of optimization reliably: the compiler has to see the _definition_ of the
function in order to be sure that the parameter is indeed declared as 'const'.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top