Note: I am using the g++ compiler (which is I hear is pretty good and supposed to be pretty close to the standard).
Not trying to start a grammar war, but just a random question... What is the ideal way to declare a pointer?
int* pI = 4;
int *pI = 4;
(or my favorite, I know it's non-pretty, but I like it):
int*pI = 4;
Same question stands for references:
int& rI = 4;
int &rI = 4;
or
int&rI = 4;
Maybe there is no right answer. Similarly, should I care whether a constant integer is declared as:
const int I = 4;
or
int const I = 4;
I'm fine with not caring...
I do like the way a const function is declared by having a const after the last parenthesis.
And I believe a constant function has a distinct function signature than the similar non-const function (i.e. the const-nesss is part of the function signature, unlike most sources that say it just depends on the arguments type and the return type).
Is this right? Should I care?
I prefer
int* a;
int& b;
for the following reason: the type is int* and not int. For me - the type belongs together and needs to stand separate from the name. I know this introduces some problems with
int* a, b;
but that's why I don't declare to variables in one line.
Other than that - like VJo said: stick to the coding standard. If everyone around you does it one way, don't do it the other.
Coding standards might tell you how to declare or define your variables.
Other then that, use whatever suits you better.
And I believe a constant function has a distinct function signature than the similar non-const function (i.e. the const-nesss is part of the function signature, unlike most sources that say it just depends on the arguments type and the return type).
A constant function has a keyword const which is appended at the end of it.
int doSomething() const;
It means that the function will not alter the state(members) of the class.
Mentioning const on an argument implies that the function will not alter the state of that variable(param in below example) being passed to the function.
int doSomething(const int param);
Mentioning const before the return type applies to the type being returned by the function.
const int doSomething();
Implies the function returns a const integer value.
So yes your understanding is correct. And there is no other way to declare a function const except putting a const after the last paranthesis.
Also, note that const member function can be only called on a const object, while a non const member function can be called by const as well as non const objects of that class.
As far as the way of declaring, Each organization have their own coding guidelines and you should stick to that, Yes there is no distinct advantage of using those contructs you mentioned in either way with respect to compiler optimization or treatment. Just follow what you like or what your organzation wants you to follow.
Bjarne Stroustrup uses:
int* a;
so, that's good enough for me.
Related
In the code review process, one of my coworkers mentioned to me that "const"s in front of "primitive types" used as a function parameter in a header is meaningless, and he recommended to remove these "const"s. He suggested using "const" only in the source file in such cases. Primitive types mean types such as "int", "char", "float", etc.
The following is example.
example.h
int ProcessScore(const int score);
example.cc
int ProcessScore(const int score) {
// Do some calculation using score
return some_value;
}
His suggestion is doing as follows:
example.h
int ProcessScore(int score); // const is removed here.
example.cc
int ProcessScore(const int score) {
// Do some calculation using score
return some_value;
}
But I'm somewhat confused. Usually, the user will look at only the header, so if there is inconsistency between the header and the source file, it might cause confusion.
Could anyone give some advice on this?
For all types (not just primitives), the top level const qualifiers in the function declaration are ignored. So the following four all declare the same function:
void foo(int const i, int const j);
void foo(int i, int const j);
void foo(int const i, int j);
void foo(int i, int j);
The const qualifier isn't ignored inside the function body, however. There it can have impact on const correctness. But that is an implementation detail of the function. So the general consensus is this:
Leave the const out of the declaration. It's just clutter, and doesn't affect how clients will call the function.
Leave the const in the definition if you wish for the compiler to catch any accidental modification of the parameter.
Function parameter declared const and without const is the same when coming to overload resolution. So for example functions
void f(int);
void f(const int);
are the same and could not be defined together. As a result it is better not to use const in declaration for parameters at all to avoid possible duplications. (I'm not talking about const reference or const pointer - since const modifier is not top level.)
Here is exact quote from the standard.
After producing the list
of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the
function type. The resulting list of transformed parameter types and the presence or absence of the ellipsis
or a function parameter pack is the function’s parameter-type-list. [ Note: This transformation does not
affect the types of the parameters. For example, int(*)(const int p, decltype(p)*) and int(*)(int, const int*) are identical types. — end note ]
Usefulness of const in the function definition is debatable - reasoning behind it is the same as using const for declaring local variable - it demonstrates to other programmers reading the code the this value is not going to be modified inside the function.
Follow the recommendations given you in code review.
Using const for value arguments has no semantic value — it is only meaningful (potentially) for implementation of your function — and even in that case I would argue that it is unnecessary.
edit:
Just to be clear: your function’s prototype is the public interface to your function. What const does is offer a guarantee that you will not modify references.
int a = 7;
do_something( a );
void do_something( int& x ); // 'a' may be modified
void do_something( const int& x ); // I will not modify 'a'
void do_something( int x ); // no one cares what happens to x
Using const is something akin to TMI — it is unimportant anywhere except inside the function whether or not 'x' is modified.
edit2: I also very much like the information in StoryTeller’s answer
As many other people have answered, from an API perspective, the following are all equivalent, and are equal for overload-resolution:
void foo( int );
void foo( const int );
But a better question is whether or not this provides any semantic meaning to a consumer of this API, or whether it provides any enforcement of good behaviours from a developer of the implementation.
Without any well-defined developer coding guidelines that expressly define this, const scalar arguments have no readily obvious semantic meaning.
From a consumer:
const int does not change your input. It can still be a literal, or it can be from another variable (both const or non-const)
From a developer:
const int imposes a restriction on a local copy of a variable (in this case, a function argument). This just means to modify the argument, you take another copy of the variable and modify it instead.
When calling a function that accepts an argument by-value, a copy is made of that argument on the stack for the called function. This gives the function a local copy of the argument for its entire scope that can then be modified, used for calculations, etc -- without affecting the original input passed into the call. Effectively, this provides a local variable argument of its input.
By marking the argument as const, it simply means that this copy cannot be modified; but it does not prohibit the developer from copying it and making modifications to this copy. Since this was a copy from the start, it does not enforce all that much from inside the implementation -- and ultimately doesn't make much difference from the consumer's perspective.
This is in contrast to passing by reference, wherein a reference to int& is semantically different from const int&. The former is capable of mutating its input; the latter is only capable of observing the input (provided the implementation doesn't const_cast the const-ness away -- but lets ignore this possibility); thus, const-ness on references have an implied semantic meaning.
It does not provide much benefit being in the public API; and (imo) introduces unnecessary restrictions into the implementation. As an arbitrary, contrived example -- a simple function like:
void do_n_times( int n )
{
while( n-- > 0 ) {
// do something n times
}
}
would now have to be written using an unnecessary copy:
void do_n_times( const int n )
{
auto n_copy = n;
while( n_copy-- > 0 ) {
// do something n times
}
}
Regardless of whether const scalars are used in the public API, one key thing is to be consistent with the design. If the API randomly switches between using const scalar arguments to using non-const scalars, then it can cause confusion as to whether there is meant to be any implied meaning to the consumer.
TL;DR: const scalar types in a public API don't convey semantic meaning unless explicitly defined by your own guidelines for your domain.
I thought that const is a hint for the compiler that some expressions don't change and to optimize accordingly. For example I was testing if a number is prime by looking for divisors up to the square root of the number and I thought that declaring the argument const would take the sqrt(n) outside of the for loop, but it didn't.
It may not be necessary in the header, but then again, you could say that all you need is to not modify the argument and it is never necessary. I'd rather see const where it is const, not just in the source, but in the header too. Inconsistencies between declaration and definition make me circumspect. Just my opinion.
Consider the following code:
class Test
{
public:
//1
int kon1() const;
//2
const int kon2();
//3
static int kon3();
};
As far as I know, the difference between function 1 and 2 is that :
Function 1 says that the function will not be able to change any data member's value
Function 2 says that it will return a const int
(If I have wrong understanding, please correct me)
My question is :
As we can see there, if we want to make a function to be const function, the const keyword is placed behind. But why in function 3, the static function, the static keyword is placed in front?
For const member functions must have the const keyword afterwards to avoid ambiguity with the return type.
For static, virtual and other keywords having a dramatic effect on how the function works, it's desirable to list it first so it's easier to see in the class definition. For example, we can quickly scan through a list of member functions and spot all the static functions, or all the virtual ones - aiding our understanding of the overall use of the function.
Marking a member function const (or e.g. an override) is a less crucial distinction - if you have a non-const object you can invoke functions whether they're const or not, the appropriate const-ness is often obvious to the reading developer as they absorb the function return type and identifier, and in some corporate/project coding standards mutating functions are grouped above const-accessors, or const and non-const versions of the same member function are side by side to emphasise their similarities - then the differet const-ness stands out more.
All these factors combine to make the actual choices in C++ optimal for development, but you're right in observing that they're a bit inconsistent.
You are mixing two concepts i.e. Storage Class with Storage Type.
C++ have following kind of storage classes
auto, register, static, extern & mutable
And following kind of storage type (based on what u can do with on storage)
read only (can be initialized ) --> this is const
read and write --> this is non const.
So when u define a variable/function u have tell in advance what kind of storage type u want to associate. Thats why u put static as first keyword in ur code.
Hope this helps.
The keyword static does not modify the variable's type. It modifies the memory address in which it will be located. It is used identically for function-type variables, and for data-type variables:
static int n; // data
static int n (); // function
The keyword const does modify the variable's type. For function-type variables, this keyword has two possible meanings:
modify the function's return value as type const:
const int n (); // function can be invoked from non-const objects only, and returns a const value
modify how this function may be invoked
int n () const; // function can be invoked const and non-const objects alike, and returns a non-const value`
int kon1() const;
This function is readonly function intended to work on const data only.
const int kon2();
This function can work on modifiable object but it returns type is readonly and caller can not modify this.
I am a C++ noob and i've a problem of understanding c++ syntax in a code. Now I am quite confused.
class date
{
private:
int day, month, year;
int correct_date( void );
public:
void set_date( int d, int m, int y );
void actual( void );
void print( void );
void inc( void );
friend int date_ok( const date& );
};
Regarding to the '&' character, I understand its general usage as a reference, address and logical operator...
for example int *Y = &X
What is the meaning of an & operator at end of parameter?
friend int date_ok( const date& );
Thanks
edit:
Thanks for the answers.
If I have understood this correctly, the variable name was simply omitted because it is just a prototype. For the prototype I don't need the variable name, it's optional. Is that correct?
However, for the definition of the function I definitely need the variable name, right?
const date& being accepted by the method date_ok means that date_ok takes a reference of type const date. It works similar to pointers, except that the syntax is slightly more .. sugary
in your example, int* Y = &x makes Y a pointer of type int * and then assigns it the address of x. And when I would like to change the value of "whatever it is at the address pointed by Y" I say *Y = 200;
so,
int x = 300;
int *Y = &x;
*Y = 200; // now x = 200
cout << x; // prints 200
Instead now I use a reference
int x = 300;
int& Y = x;
Y = 200; // now x = 200
cout << x; // prints 200
In this context, & is not an operator. It is part of the type.
For any given type T, the type T& is a "reference to T".
The symbol & in fact has three meanings in C++, and it's important to recognise those different meanings.
"address of" when applied to an expression
"reference" when part of a type
"bitwise AND" when applied to two numbers
Similarly, * has at least three meanings, and once you've grasped those, you'll have pointers and references down. :-)
If I have understood this correctly, the variable name simply was omitted there because it is just the prototype. And for the prototype i don't need the variable name, it's optional. Is that correct?
Yes.
However, for the definition of the function I need definitely the variable name, right?
No. Although you'll usually want it (otherwise what's the point?!) there are some circumstances in which you don't, usually when you've only introduced the parameter to engage in overload-related trickery.
But speaking purely technically you can omit the argument name from the declaration and/or the definition as you wish.
So, for starters, I think you might be more confused in that the author of that code omitted something quite important (although optional): the variable name.
Let's rewrite that:
friend int date_ok( const date& check);
The type of the variable 'check' is const date&. We are passing it to the function as a 'constant reference'. In other words, it's an alias to whatever we passed in (via pointer magic), but we cannot modify it.
The reason that we do this is so that we can pass large objects (like a std::vector) into functions without making a copy of them. Pass by value incurs a copy operation. For an int, that doesn't matter (it takes next to no time), for a class, it might be more significant. The rule of thumb is to always pass objects by reference, and to pass them by const reference if you don't intend to modify them. (This rule of thumb ignores move semantics, but I'll assume you don't know about that yet).
using & at the end of a type in a function prototype allows passing-by-reference, instead of passing-by-value (copy).
This way you can modify the date object in the friend function.
friend int date_ok( const date& );
Friend:
In your class definition this mean that you're telling that a function date_ok can access to all parameters of your class. In deed it means that it is almost a member of your class, so consider adding this friend function rather as a member function. (unless you have other good reasons, like not polluting your class with foreign definitions)
If yes, also consider making that a static function, it could have all the same access to the guts of your date object class. But that would be more natural.
cf. the book "101 C++ coding standard". Prefer defining static member functions, it favours loose coupling.
Thanks for the answesers.
If I have understood this correctly, the variable name simply was omitted there because it is just the prototype. And for the prototype i don't need the variable name, it's optional. Is that correct?
However, for the definition of the function I need definitely the variable name, right?
///////////////////////////////////////
class A {
...
const double funA(void)
{...}
};
A a;
double x = a.funA();
// although the intention is to
// enforce the return value to be const and cannot be
// modified, it has little effect in the real world.
class A2 {
...
double funB(void)
{...}
};
///////////////////////////////////////
class A {
void setA(const double d)
{ // now you cannot change the value of d, so what?
// From my point of view, it is NOT a good practice to change the pass-in parameter
// in this case, unless you want the caller to receive that change
// instead, you can do
// const double dPassIn = d;
/ /then use dPassIn instead.
...
}
};
class A2 {
void setB(double d)
{...}
};
//////////////////////////////////////
From my understanding, we should prefer to
using A2::funB and A2::setB because the const used in
both A::funA and A::setA has little meaning.
// Update //
FMOD_RESULT F_API EventSystem::getReverbPresetByIndex(const int index,
FMOD_REVERB_PROPERTIES *props, char **name = 0);
I consider FMOD is a well-designed package and it does use const int inside function parameter list.
Now, I agree that the A::setA(const double d) has its edge.
When returning by value the constant has no effect as it cannot be enforced anyway. Some compilers issue a warning. However it DOES make sense to return a pointer/reference to constant data.
When passing an argument into a function it is preferable (safer, allows for compiler optimizations) to pass it as a constant unless you absolutely need to change the data.
the const-keyword tells the Compiler "In my function setB i Wont change the Argument. If you want to Optimize for Multithreading you can use this Variable the same Time in another context, because my Work wont change it."
So i would say, in Progamming-logic, the second variant is better, like you said it has "little meaning", but in wider logic if you see what really happens, you should declare const, what is const, and dont declare const what isnt const. It is kind of a documentation the compiler understands and maybe will use to optimize your code!
From my point of view, it is NOT a good practice to change the pass-in parameter
Then it makes sense to declare that by using the const on the argument in the definition of the function. Not everybody follows the practice, so having the const on the argument is better for future readers of your code than having to scan the whole function body for modifications to the argument.
And even if you follow the practice it's easy to modify a variable by mistake (the classic typo of = instead of == or passing the arg via non-const ref or pointer). The const argument in the implementation prevents this.
On the other hand const int argument in the declaration (if separate from definition) does not make sense.
In practice, there is no real benefits for scalars.
However, in theory it could help a compiler to perform additional optimizations, such as passing a reference to the constant instead of copying the double value.
I have the following function declaration:
void fn(int);
This function has a single integral type parameter. Now, I could call this function by passing a non const or a const integral object. In either case, this function is going to copy the object to its local int parameter. Therefore, any modifications to this parameter is going to be local to the function and is not going to affect the actual arguments of the caller in any way. Now my question is under which scenario will I declare this single int parameter to be of const type? I don't see a need to declare this function as follows.
void fn(const int);
This is because the arguments are going to be anyway passed by value and the function can in no way modify the arguments in either case. I understand that by declaring a parameter constant the function cannot modify it inside its body. However, there is no downside here even if the function modifies since the parameter is local to the function.
You're right that to the caller there is no difference -- it only matters inside the function. I prefer to add the const whenever I can. As I'm writing the function, I'm thinking "I want this parameter but have no intention of modifying it (even just locally)" and the compiler will keep me honest.
Also, in some cases the compiler may be able to do more optimizations if it knows the variable is const (as in loop bounds).
Just because it's allowed, doesn't mean there's a point to it.
I wouldn't be surprised if this could cause overloading to behave slightly differently, but I think you're basically right - there's no good outside-the-function reason to do it.
One possible problem is confusing readers who might think you intended a reference instead, but forgot the "&".
Sometimes templates are written in a general way, and end up doing things like that. With function template parameter deduction, though, that const tends to get thrown away.
this is effectively a const argument. It is a pointer, but it's immutable in the sense of your example. (Of course, this is a keyword, not a variable, and unary & doesn't work with it.) If you want an argument to behave like that, declare it const.
From the C++ Spec: http://www.kuzbass.ru:8086/docs/isocpp/over.html
Parameter declarations that differ
only in the presence or absence of
const and/or volatile are equivalent.
That is, the const and volatile
type-specifiers for each parameter
type are ignored when determining
which function is being declared,
defined, or called.
Example:
typedef const int cInt;
int f (int);
int f (const int); // redeclaration of f(int)
int f (int) { ... } // definition of f(int)
int f (cInt) { ... } // error: redefinition of f(int)
A favorite interview question in C++ interview is what is the difference between passing by values, passing by pointer and passing by reference.
In this case we are passing by value and that too int and hence it will not matter. But I am not sure about the user created classes. In that case when the compiler see the object is passed by const value it may decide to pass it by the const reference. Nowdays compilers are intelligent and I don't see why they can not do it.