In this code I change iType variable which is a function parameter. It works fine, but is it correct?
void ImgCoreQCV::IPThreshold( double dThresh, double dMaxval, int iType, bool bTreshOtsu ) {
if(bTreshOtsu)
iType |= THRESH_OTSU;
if(undoVector.back().channels()!=1)
cvtColor(undoVector.back(),CurImg,CV_BGR2GRAY);
threshold(CurImg,CurImg,dThresh,dMaxval,iType);
}
I mean that I did not create a new variable and has changed it:
int iThreshType = iType;
if(bTreshOtsu)
iThreshType = iType | THRESH_OTSU;
threshold(CurImg,CurImg,dThresh,dMaxval,iThreshType);
It is correct in this particular case, and it has no side effect since the argument here is a copy of the actual parameter passed.
But it might make a trouble in general case, if you unintentially change parameter passed by reference.
Also modifying parameters usually make the code worse readable. And might require more time for understanding what is really happening in the function.
So, generally I wouldn't recommend modifying parameters. Leave this optimization to the compiler.
As long you don't have by reference parameters, changing the value won't have any effect outside of your function.
It's fine to do so and you don't need a extra variable.
You can create a temporary variable inline of the lowest function call like this:
threshold(CurImg,CurImg,dThresh,dMaxval, bTreshOtsu ? iType|THRESH_OTSU : iType);
There are a couple of things that you should be clear on regarding function parameters:
void IPThreshold( double dThresh, double dMaxval, int iType, bool bTreshOtsu );
The above function will pass copies of each of the parameter values to the function body. When invoked with a local variable then the value of the local variable is unchanged after you modify it in the function.
void IPThreshold( double& dThresh, double& dMaxval, int& iType, bool bTreshOtsu );
Above the function will use non-const references which means that you can modify the value of the referenced parameter within the function. If you call this version with a local variable and you modify the parameter then the local variable will be modified after the call returns.
You also ask if this is okay... well I personally attempt not to use parameters for this if I can avoid it as I think that return values are generally clearer. However there is nothing wrong with it. The only caveat I would say is that you should be consistent with the meaning of how you pass your parameters.
Related
When I pass a variable by reference like this:
void function(int &r){
//do something
}
int main(){
int a = 100;
function(a);
return 0;
}
What actually happens ? Does r contain the address of an integer variable or something ? How does it find it ?
Reference of your integer a will be passed as argument to your function. Now in your function, if you change the value pointed by r, it will be reflected in a as well.
So if you assign r=2 in your function and print out a in main, you will see that a has the value 2.
Your program has some syntax errors, but I can understand what you wanted to convey.
Edit:
From the user perspective, it's as if you were receiving a value in the function except that modification done to it are visible from the caller. It's also cheaper in terms of performance when passing big objects because no copy is needed.
How it works in practice is that the compiler actually pass a pointer to the function. But since the caller must have a valid object to pass to the function, a reference can't be invalid contrary to a pointer so you don't need to check for NULL values.
I have for example this:
void SetWidth(double width);
Should it be:
void SetWidth(const double width);
No, you shouldn't.
The compiler treats the two function signatures as identical, so about all you can accomplish by adding const in a case like this is mislead the reader. For one obvious example, a reader who doesn't know C++ quite so well might believe that having both:
void SetWidth(double) {}
void SetWdith(const double) {}
...would be legitimate function overloading. This, of course, is wrong -- as already noted, the compiler treats the two as identical, so this would simply violate the one definition rule.
The const does prevent you from modifying the parameter inside the function, but if your function is large enough that you think you need this (i.e., you're having difficulty keeping track of what's being modified and what isn't), then chances are pretty good that you need to rewrite the function.
From the caller's viewpoint, both are equivalent. You can (and, to reduce noise, should) leave that const out of a declaration, and only include it in the definition.
From the implementor's viewpoint, you might want to do it for the same reason you might want any local variable to be constant: to be sure that it won't change by accident.
For,
Void SetWidth(double width);
We can change the value of the variable width with in the function SetWidth(). But, the changed value will not reflect back to the called function. Say,
class A_Class
{
public:
void SetWidth(double width) {
width=width+10;
this._width=width;
std::cout<<"IN SetWidth:"<<width;
}
private:
double _width;
};
int main()
{
A_Class aObj;
double twidth=20.9;
aObj.SetWidth(twidth);
std::cout<<"twidth:"<<twidth;
return 0;
}
O/P: IN SetWidth:30.9
twidth:20.9
So, it doesn't matter if make it as const, which you have mentioned in the other proto-type [void SetWidth(const double width);].
Internally compiler allocates memory for 'width' variable in the stack and copies the value to that variable.
If you use the second proto-type[void SetWidth(const double width);] it ensures that variable width is constant can not be changed inside the function.
Hope this helps.
They are almost equivalent.
The only difference is that you tell to the compiler that the variable width cannot be modified inside the function scope when you use const.
Short answer: implement a function that takes a const argument by value when it makes sense to ensure (or explicitly express) that: "This argument will not change inside the body of this function."
and implement a function that will take const argument by reference, when you want to explicitly tell the caller: "This function will not change the argument you're passing to it."
(In case of the "setter" taking an argument by value - such as SetWidth - it doesn't make much of a sense to use const)
If the function is not expected to modify the local variable width, you should declare it const. This way, if you inadvertently try to assign to the variable, or assign its address to a non-const pointer (since that could allow it to be modified), the compiler will issue a warning.
There's no difference in the generated code in either case, it just enables these additional safety checks.
Is there any benefit (or conversely, cost) to passing a parameter by const value in the function signature?
So:
void foo( size_t nValue )
{
// ...
vs
void foo( const size_t nValue )
{
// ...
The only reason for doing this that I can think of would be to ensure the parameter wasn't modified as part of the function although since it has not been passed by reference there would be no wider impact outside the function.
The top-level const here affects only the definition of the function and only prevents you from modifying the value of nValue in the function.
The top-level const does not affect the function declaration. The following two declarations are exactly the same:
void foo(size_t nValue);
void foo(const size_t nValue);
Of course there is. You can't modify nValue inside the function.
As with const-ness in general, it's not a security measure, since you can cast it away, but a design matter.
You're explicitly telling other programmers that see your code -
"I will not modify nValue inside this function
and programmers that maintain or change your code
"If you want to modify nValue, you're probably doing something wrong. You shouldn't need to do this".
Using const you also ensure that you're not incorrectly trying to alter the value of the parameter inside the function, regardless if the parameter is modifiable or not.
if you define the input parameter const, you can just call const functions on that object.
anyway if you try to change that object accidentally, you will get a compiler error.
I've recently decided to do this. I like doing it as a sort of consistency with const & and const * parameters. const correctness makes life better, so why not go all in for it? If you know you're not going to change the value, why not make it const? Making it const communicates that intention clearly.
///////////////////////////////////////
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.