C++ clarification of "return" - c++

Homework, just advise please
Apparently my idea of what returning something in a method does is wrong. I'm trying to write methods for getting derivatives of numbers and operations. So far I just wanted to get the derivative of a non-negative number that isn't accompanied with an "x" (result should be zero no matter what value is given).
The code is pretty long and needs to be cleaned up so I'll just include the method, the call, and what I'm getting.
Method:
int noXDerivative(int tempInt, string tempX)
{
if (tempX == "")
{
tempInt = 0;
}
return tempInt;
}
void getDerivatives(int tempInt, string tempX, int tempInt2, string tempX2, char tempOperator)
{
noXDerivative(tempInt, tempX);
noXDerivative(tempInt2, tempX2);
}
The call:
getDerivatives(tempNumInt, tempNumX, tempNum2Int, tempNum2X, expression[iterator]);
I also called the "noXDerivative" directly to see what would happen but the result didn't change. The test I'm running right now is "5 + 6" (tempNumInt is 5 and tempNum2Int is 6). I keep getting 11 when I need to get 0 (again, there are no "x"s). I was hoping that if I put tempNumInt as one of the parameters it would be changed from 5 to 0 within the noXDerivative method but it doesn't. How do I correct this?

I have to say that I don't understand what it is that you're trying to do.
Nevertheless, to achieve your goal of modifying tempInt inside getDerivatives(), you can either do:
tempInt = noXDerivative(tempInt, tempX);
Or, you can modify the noXDerivative() function to take its argument by reference, rather than by value:
int noXDerivative(int &tempInt, string tempX)
{
...
}

return does just that--it returns a value. It doesn't change the value passed in. If I understand your code correctly, I bet that if you had something like
int result1 = noXDerivative(tempInt, tempX)
result1 would hold the value 0. Mind you, tempInt and tempInt2 in getDerivatives won't be modified then, so you'll need to figure that out...

well, not a lot to "advise". The problem here is that when a routine returns a value, the call must be used as a left hand value.
tempInt = noXDerivative(tempInt, tempX);
You will not modify the value of tempInt otherwise, at least with the current signature of your routine. You are passing tempInt as an argument by value with that call, and any modifications you perform to tempInt will occur on the local stack frame of that routine.

Related

Void and cout vs int

I was working on an assignment and decided on checking this following problem with my POD. The assignment basically requires a generation of a multiplication problem and loop forever depending on if he gets it right or wrong. So to generate my problem:
int Elementary::setProblem()
{
srand ( time(NULL));
firstfactor = rand() %1;
secondfactor = rand() %1;
answer = factor1 * factor2;
return answer;
}
However, I was told that this method was the proper way of doing:
void Elementary::setProblem()
{
srand ( time(NULL) );
firstfactor = rand()%10;
secondfactor = rand()%10;
answer = firstfactor * secondfactor;
}
She basically told me that answer = is already sets the private member and that return had no use.
Wouldn't my method be faster since I don't have to set the problem and then make a second function to get the problem?
A setter function, typically, does not return anything.
The whole point of pairs of setter and getter functions is that you call one to set something, another to get the value back. That way, you could, for example, completely avoid storing answer, and just calculating it in the getter when you actually need it - in this particular case, this probably gives no benefit, but in some cases, that may be a benefit.

Why does std::atomic's compare_exchange take a reference for the expected value?

What is the reason for std::atomic<T>::compare_exchange_* taking the expected value by reference, instead of taking it by value?
compare_exchange_* changes expected to actual value if operation fails. It makes loops a bit simpler.
Here's a common usage pattern:
atomic<int> foo;
int expected = 3;
while(!foo.compare_exchange_strong(expected, 4)) {
// somebody beat us to it
// now decided what to do; break the loop? try again?
if (expected == 4) {
// somebody already wrote a 4 there
break;
} // otherwise keep trying
}
It could return a pair<bool,T> instead, but it would be less convenient for this use case. It could return the value in another argument, but you would have to copy into expected manually before you tried again.
IMHO this is a good trade-off, even though it won't let you pass a constant in the first argument (as it's a rare use case).

recursive divison of number

I have following code to divide one number recursively by another number:
#include <iostream>
using namespace std;
int divide(int number,int dividend){
int answer=0;
if (number>dividend || number==dividend ){
answer+=1;
return divide(number-dividend,dividend);
}
return answer;
}
int main(){
cout<<divide(20,5)<<endl;
return 0;
}
but unfortunately I get zero as answer. Do you see what is wrong?
Answer is a local variable. When you run this code, the first call to divide creates an instance of the answer variable, sets it to 0, and then increments it to 1. Then, when you recursively call divide again, it creates a brand new instance of the answer variable, sets that instance to 0, and then increments that instance to 1.
In your final call to divide, it creates a brand new instance of the answer variable, sets that instance to 0, but since now number<=dividend it doesn't increment it, and it returns that instance of answer which is 0.
In the if branch you are incrementing answer but returning something unrelated (the result of the recursive call). I am sure, this is not what you want. Go from there.
You are recursively running the following code:
if (number>dividend || number==dividend ){
answer+=1;
return divide(number-dividend,dividend);
}
But once the recursive calling ends (which is number < dividend), you will ignore the if statement and return 0;
You do int answer=0; in the start of function call, so when the if statement is wrong, it returns 0 so you should define it as input parameter (by reference call) or make it global (not recommended) and do not set it to zero, just set it before your recursive function call.

STACK.peek function, having some trouble, C++

CARD& STACK::peek()
{
if(cards.size == 0)
{
CARD temp = CARD {-1, -1};
return temp;
}
return cards.back();
}
This is the function I am having trouble with.
CARD is just a struct with two int variables, called rank and suit.
STACK is a class that manages an std::vector<CARD>, that is called cards.
The function is supposed to return a reference to the card on top of the stack, or return the reference to a dummy card if the vector is empty.
First of all, I get a warning that says a reference to a local variable temp is returned. What is wrong with that? How will that effect the function? What do I do about it?
Second, I am trying to use this function with another function I created called cardToString
char* cardToString(CARD& c);
It is supposed to use the rank and suit variables in the passed CARD to look up string values in a table, concatenate the two strings together, and return a pointer to the new string.
So the end result looks like:
cout<<cardToString(deck.peek())<<"\n";
but this line of code will execute up to the cardToString function, then just stop for some reason. It is annoying the hell out of me because it just stops, there is no error message and there does not look like there is anything wrong to me.
Can somebody help me out?
Edit: here is the cardToString function
char *cardToString(const CARD& c)
{
if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0)
{
std::cout<<"returned null";
return NULL;
}
char *buffer = new char[32];
strcpy(buffer, RANKS[c.r]);
strcat(buffer, " of ");
return strcat(buffer, SUITS[c.s]);
}
I specifically want the function STACK.peek() to return the address of the CARD that already exists on the top of the STACK. It seems to make more sense to do that than to create a copy of the card that I want to return.
First of all, I get a warning that says a reference to a local variable temp is returned. What is wrong with that? How will that effect the function? What do i do about it?
A local variable, as it name implies, is local to the function it belongs to, so it's destroyed as the function returns; if you try to return a reference to it, you'll return a reference to something that will cease to exist at the very moment the function returns.
Although in some cases this may seem to work anyway, you're just being lucky because the stack hasn't been overwritten, just call some other function and you'll notice it will stop working.
You have two choices: first of all, you can return the CARD by value instead of reference; this, however, has the drawback of not allowing the caller to use the reference to modify the CARD as is stored in the vector (this may or may not be desirable).
Another approach is to have a static dummy CARD instance stored in the STACK class, that won't have these lifetime problems, and that can be returned when you don't have elements in the vector; however, you should find a method to "protect" its field, otherwise a "stupid" caller may change the values of your "singleton" dummy element, screwing up the logic of the class. A possibility is to change CARD in a class that will encapsulate its fields, and will deny write access to them if it's the dummy element.
As for the cardToString function, you're probably doing something wrong with the strings (and I'm almost sure you're trying to return a local also in this case), but without seeing the body of the function it's difficult to tell what.
By the way, to avoid many problems with strings I suggest you to use, instead of char *, the std::string class, which takes away most of the ugliness and of the low level memory management of the usual char *.
Also, I'd suggest you to change cardToString to take a const reference, because most probably it doesn't need to change the object passed as reference, and it's good practice to clearly mark this fact (the compiler will warn you if you try to change such reference).
Edit
The cardToString function should be working fine, as long as the RANKS and SUITS arrays are ok. But, if you used that function like you wrote, you're leaking memory, since for each call to cardToString you make an allocation with new that is never freed with delete; thus, you are losing 32 bytes of memory per call.
As stated before, my tip is to just use std::string and forget about these problems; your function becomes as simple as this:
std::string cardToString(const CARD& c)
{
if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0)
return "(invalid card)";
return std::string(RANKS[c.r]) + " of " + SUITS[c.s];
}
And you don't need to worry about memory leaks and memory allocations anymore.
For the reference/value thing: if the caller do not need to use the reference to modify the object stored in the vector, I strongly suggest passing it by value. The performance hit is negligible: two ints instead of one pointer means 8 vs 4 bytes on most 32 bit architectures, and 8 bytes vs 8 bytes on most 64 bit machines (and also accessing the fields via pointer has a small cost).
This kind of micro-optimization should be the last of your concerns. Your top priority is to write correct and working code, and the last thing you should do is to let micro-optimization get in the way of this aim.
Then, if you experience performance problems, you'll profile your application to find where the bottlenecks are and optimize those critical points.
You cannot return a reference to a local variable, because the local variable no longer exists when the function returns.
You need to return by-value, not by-reference (i.e. CARD STACK::peek() { ... }).

referencing a vector

I have this code
void split(vector<float> &fvec, string str)
{
int place = 0;
for(int i=0; i<str.length(); i++)
{
if(str.at(i) == ' ')
{
fvec.push_back(atoi(str.substr(place,i-place).c_str()));
place=i+1;
}
}
fvec.push_back(atoi(str.substr(place).c_str()));
}
What im trying to do is pass a reference to a vector into the method so it splits the string i give it into floats without copying the vector... i dont want to copy the vector because it will be containing 1000's of numbers.
is it not possible to pass a vector by reference or am i just making a stupid mistake?
if it helps heres the code im testing it out with
int main (void)
{
vector<float> fvec;
string str = "1 2 2 3.5 1.1";
split(&fvec, str);
cout<<fvec[0];
return 0;
}
It is indeed possible. You're just using the wrong syntax. The correct way to do it is :
split(fvec, str);
What you're doing is wrong because it passes the address of the vector as the intended reference.
If you are using a modern compiler, like gcc/g++, it does named return value optimization for you, so that you don't need to pass the return value by reference or pointer.
See:
http://en.wikipedia.org/wiki/Return_value_optimization/
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
You are passing the address of the vector. (split(&fvec, str);)
The call should be split(fvec, str); without the &.
The obvious thing that leaps out is the split(&fvec, str); in your main function, which means you're not passing a vector but the address of a vector. This is the right thing to do if your vector parameter is a pointer, but not if it's a reference. Use split(fvec, str); instead.
Also, one thing you might consider is building the vector in the function and returning it as normal. This is likely to be optimized out by the compiler. If you're not using a compiler with return value optimization ability, you're likely to get better results by changing compilers than trying to tune your code manually.
And, if you're worried about passing big data structures around, what of the string parameter? Doesn't that get large?