Failing to change members of structs stored in two-dimensional array - c++

I have a global two dimensional array holding a number of structs. From inside a function I try to change it's members like this:
struct ControlPin {
int pin;
int previousValue;
};
ControlPin controls[CHANNELS][MULTIPLEXERS];
void readControlInput(int channel, int multiplexer) {
ControlPin control = controls[channel][multiplexer];
control.previousValue = analogRead(control.pin);
}
If i print out control.previousValue inside readControlInput() I can verify that it has changed, but after getting out of the function scope, the change is gone. How can I get a reference to the struct instead of copying it? I assume that's what happening, but I cant see why. I know that when you pass a value as a parameter to a function it is actually a copy, but here I'm accessing the global array directly?
I'm used to Java so this is a bit confusing to me.

In Java all objects are (IIRC) references. In C++ the default is that objects are values. When you do
ControlPin control = controls[channel][multiplexer];
you copy the "value" in controls[channel][multiplexer], then when you modify control you only modify the local value, and not the value in the array.
The simplest option is to explicitly say that control is a reference, by using the ampersand (&) when declaring the variable:
ControlPin& control = controls[channel][multiplexer];
// ^
// |
// Note ampersand here
That tells the compiler that control is a reference and then initializes it to reference the object (value) at controls[channel][multiplexer].
On an unrelated not, C++ have no bounds-checking. If you access an array out of bounds the compiler will happily allow it, but it will lead to undefined behavior at run-time. You need to do bounds-checking yourself if you want to avoid weird problems. It doesn't have to be in the function, but it needs to be done somewhere.

You're not accessing the array directly, this works exactly like if you had passed the element to a function:
void readInput(ControlPin control)
{
control.previousValue = analogRead(control.pin);
}
void readControlInput(int channel, int multiplexer) {
readInput(controls[channel][multiplexer]);
}
You can tell from the types - ControlPin means the same thing regardless of whether it is a local variable or a parameter.
In C++, variables that contain class instances always contain class instances and not some kind of "reference" to them, so just like when calling a function,
ControlPin control = controls[channel][multiplexer];
creates a copy of the array element, and
control.previousValue = analogRead(control.pin);
modifies that copy.
The simplest fix is to write it in one line:
controls[channel][multiplexer].previousValue = analogRead(control.pin);
You can also use a reference variable (which is different from Java's "references") to refer to the array element itself:
ControlPin& control = controls[channel][multiplexer];
control.previousValue = analogRead(control.pin);
This is most useful if you need to do more than one thing with the same element - it's both more readable and more resilient to errors than duplicating the indexing.

Related

Easiest way to modify a const variable's value

For my CS class I have a variable const int m_vin, throughout my code I am required to edit this value. I was under the impression that const variables cannot be edited. How would I go about this?
Edit:
Here are the directions for m_vin which is a member variable of an Object named Vehicle:
m_vin, a const int which represent a unique VIN–Vehicle Identification Number (no two vehicles can ever exist with the same m_vin).
In my program I am required to edit m_vin;
Word of caution: Modifying the value of such an object, no matter the technique used to do it, is cause for undefined behavior.
You could use:
int& ref = const_cast<int&>(m_vin);
ref = <new value>;
Don't blame me if your computer blows up.
It will be better to change the variable to be a non-const one.
int m_vin;
You should ask your professor/teaching assistant why is the const used there if the value of the variable is expected to be modified through out the code. That does not make sense.
You don't.
That's the whole point.
"For my CS class I have a variable const int m_vin, throughout my code I am required to edit this value." - Don't do that. You'll invoke Undefined Behaviour.
Create a copy. Edit the copy. Save the copy back to "wherever".
Don't try to modify const variables. Even though the language gives you tools to write code that will do it and that will compile, you will have code that has no well defined behaviour. Don't do that.
Constants (also called literals) are fixed values once declared and initialized. unlike variables whose value can be altered, constants - as the name implies does not change, they remain constant. Constant must have to be initialized at the time of creating it, and new values cannot be assigned later to it.
Consider using a variable if the value will ever change during the program execution.
Do not do this. Ever. As stated by R Sahu, you can try const_cast to remove const'ness. However, this is not the only guard to fight with. Sometimes (especially if this is a global-scope defined item), memory page that contains the const items could be marked as read-only by OS (I met such a thing on Win XP). So, your attempt to modify const_cast'ed item could end up with Access Violation or similar.
Again: do NOT do this.
For my CS class I have a variable const int m_vin, throughout my code I am required to edit this value. I was under the impression that const variables cannot be edited. How would I go about this?
As others have pointed out, you can't, at least not directly. And it's not good programming to even try.
Here are the directions for m_vin which is a member variable of an Object named Vehicle: m_vin, a const int which represent a unique VIN–Vehicle Identification Number (no two vehicles can ever exist with the same m_vin).
Most likely your instructor is asking you to construct different objects with differing const int m_vin. If you do that you don't need to edit them after construction since each object is initialized with a different vin.
In my program I am required to edit m_vin;
However, assuming this is sort of a programming challenge, you can change a const member variable by instantiating a new object initialized with the different value. This is best done in a friend function so you can access private variables.
One way to accomplish this is using placement new together with a constructor that has all values needed to initialize the object. First save copies of all the values in the object locally. Use std::move for dynamic values. Next, call the destructor on the object. Then use placement new with the argument list needed to reconstruct the object with the new const value.
The following code replaces m_vin with a different value.
#include <memory>
#include <string>
struct Foo {
const int m_vin;
std::string stuff;
Foo(int m_vin_, std::string stuff_) : m_vin{ m_vin_ }, stuff{ stuff_ } {}
~Foo() {}
};
int main()
{
Foo foo1(1, "SomeString");
int ci = 42 // modify ci
std::string stuff = foo1.stuff;
foo1.~Foo(); // in case there is any dynamic objects in Foo
new(&foo1) Foo(ci, stuff);
std::string x = foo1.stuff;
}
But be warned. You should also use std::launder to guarantee the const member will be correctly read. This sort of hack, while legal (I think), harms the readability of the code. People reading the code will, reasonably, assume that const member variables will not change after they are constructed. So don't do it other than to pacify an instructor with a weird request.

Why, or in what situations, would you pass an argument to a function as a reference (or pointer) in C++?

I am used to passing arguments regularly in my own code but frequently stumble upon function arguments being passed by reference or pointer while reading over others' C++ code. I do not understand what is the purpose of doing so. Can somebody please explain this?
There are essentially three reasons why this is done.
Reduced memory usage
Every time you call a function the arguments are copied and passed. This isn't a big deal when you are passing around numbers. However when you are dealing with big chunks of memory, like objects, structs, arrays etc. this becomes very expensive.
So all complex types are typically passed as pointers. If you are throwing around objects you are always working with a pointer.
The const qualifier should be used in this instance to indicate that the variable won't be changed.
Modify the argument
Sometimes it is useful to modify the passed argument, though this should be avoided as bad style. The best example I think is modifying an array, for example a push() function. Another is modifying an objects public members, or when you want to return multiple values from a function.
Note that this can be a source of bugs. If you are modifying a passed variable it should be obvious from the name of the function that this is what you are doing.
Low level memory access
Anything which directly works with memory will want direct access to said memory. Standard practice in C but less common in C++. Look at functions like memcpy() and anything else from <string.h>.
If I pass a bunch of characters to a function, I can change them inside it and they will remain unchanged outside the function. This means if you wish to capitalise some text, you'd have to make a copy of it, then change some of the letters.
If on the other hand, you told the function the address of that string in memory, it could then change the existing string without making a copy. Sometimes, the arguments required will consume a trivial size. Other-times, the data required make take several hundred mega/giga/tera bytes. The last thing you want to do is read all that in, then make a copy of it that you can send off to a function.
The difference between references and pointers is mostly convenient syntax for the programmer, but there are important exceptions to this rule.
If you pass argument to a function, you can change it inside the function. Once the execution of that function has finished, the passed in variable will rename unchanged.
int square_this_number(int x)
{
int y = 0;
y = x * x;
x = 1000;
return y;
}
int a = 10;
int b = 0;
b = square_this_number(a);
/* a is still 10, not 1000. */
/* b is 100. */
Pass by reference or pass by pointer means that you want to keep the change once the execution of function has finished.
int try_square_and_change_input(int& x)
{
int y = 0;
y = x * x;
x = 23;
return y;
}
int a = 5;
int b = 0;
b = try_square_and_change_input(a);
/* a is now 23 instead of just 5. */
/* b is 25 of course. */
You may refer to this page: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/com.ibm.zos.v2r3.cbclx01/cplr233.htm
Reasons to do this include:
I need to modify a variable that is not local to the called function.
I want to pass a single word to the function, rather than make a copy of a large structure or array (and possibly another if I need to modify it).
It's a pointer to shared memory and I want changes to be visible in different processes or threads.
It's a pointer to a polymorphic struct or union (or class in C++) and I want the function to be able to determine the correct type at runtime.
The size and type of the data might vary, as with memcpy().
The type should be opaque to client code.
That's just how the interface is specified.
Pass by value: when we don't want to change variables value from called function.
Pass by reference: (only. In c++, not in c): when we want to do changes in variabe by called function.
Pass by pointer: from periferi it works same as reference, but there exist differences..

Making changes to object state from within a function

I have had to simplify some of my code to ask this question. However, in the below code does the fact that I am not declaring x as a reference type mean my change of decrementing will get "forgotten" once the function has exited?
The smartest way to fix this would be to declare x as AnotherClass& x?
void MyClass::myFunc(unordered_map<int, AnotherClass>* dictionary, int z, int y){
AnotherClass x = dictionary->at(z);
//Does this change on x get "forgotten" in terms of what dictionary stores
//once myFunc() has finished, because x is not a reference/pointer type?
x.changeSomething(y--);
}
class MyClass{
public:
private:
myFunc(unordered_map<int, AnotherClass>* dictionary, int z);
unordered_map<int, AnotherClass>* dictionary
};
Correct. x is a copy of an element of dictionary. You are applying changes to the copy, which is local to the function. You should see no effects in the caller side. You can either take a reference, or act directly on the result of the call to at:
dictionary->at(z).changeSomething(z--);
Note that this has nothing to do with the code being inside a function.
In languages like Java or C# when you write Thing t = s; you are actually creating an alias t that refer to the same object in memory than s refer to. In C++, however, values and aliases are strictly separated:
Thing t = s; is about making a copy of s
Thing& t = s; is about creating an alias referring to the same object than s (a reference)
Thing* t = &s; is about creating an alias referring to the same object than s (a pointer)
The difference between references and pointers does not matter here, what matters is the difference between copies and aliases.
Changes to a copy are local to that copy
Changes to an object via an alias are local to that object, and visible through all aliases referring to that object
In term of your example:
// Fix 1: take dictionary by *reference* and not by *pointer*.
void MyClass::myFunc(std::unordered_map<int, AnotherClass>& dictionary, int z, int y){
// Fix 2: dictionary.at(z) returns a "AnotherClass&"
// that is an alias to the element held within the dictionary.
// Make sure not to accidentally make a copy by using that "&"
// for the type of x.
AnotherClass& x = dictionary.at(z);
// "x" is now a mere alias, the following call is thus applied
// to the value associated to "z" within "dictionary".
x.changeSomething(y--);
}
Note that you could write dictionary.at(z).changeSomething(y--); in this case; however there are several shortcomings:
if x is reused more then once, naming it makes it clearer.
in cases where the function/method invoked have side-effects, the number of calls is important and need be controlled.
from a performance point of view, avoiding unnecessary computing the same thing over and over is always welcome... but don't get too hang up on performance ;)

passing a vector of pointers and erasing duplicates

I am trying to erase a vector of pointers that I pass by value into some function. The reason why I pass by value is that I plan to erase these values in numerous calls to the function. So if I pass by pointer/reference I could not achieve this.
First of all is the statement above correct?
Here is some example code:
vector<Boson*>* BosonMaker::remove_duplicates(vector<Boson*>* boson_candidates, vector<Particle*> child_candidates){
vector<Particle*> used_leptons.clear();
// This needs deleting at some point
m_unduplicated_bosons = new vector<Boson*>();
for(int i_b = 0; boson_candidates->size(); i_b++){
vector<Particle*>::iterator child1_finder = find(used_leptons.begin(), used_leptons.end(), boson_candidates->at(i_b)->Child1());
//Search pointer will reach end of collection if child isn't in the used_leptons vector
if (child1_finder == used_leptons.end()) {
vector<Particle*>::iterator child2_finder = find(used_leptons.begin(), used_leptons.end(), boson_candidates->at(i_b)->Child2());
if (child2_finder == used_leptons.end()) {
used_leptons.push_back(boson_candidates->at(i_b)->Child1());
used_leptons.push_back(boson_candidates->at(i_b)->Child2());
// And add the boson to the vector of final bosons
unduplicated_bosons->push_back(boson_candidates->at(i_b));
}
}
}
// Now make a vector of unused leptons
for (int i_l = 0; i_l < used_leptons.size(); i_l++) {
vector<Particle*>::iterator lepton_finder = find(child_candidates.begin(), child_candidates.end(), used_leptons.at(i_l));
child_candidates.erase(lepton_finder);
}
return unduplicated_bosons;
}
I would then use this member function inside the class like so
vector<Boson*> *m_boson_finals_elpair = remove_duplicates(&m_boson_electronPair_candidates, m_all_particle_candidates);
vector<Boson*> *m_boson_finals_mupair = remove_duplicates(&m_boson_muonPair_candidates, m_all_particle_candidates);
vector<Boson*> *m_boson_finals_elneutrino = remove_duplicates(&m_boson_electronNeutrino_candidates, m_all_particle_candidates);
vector<Boson*> *m_boson_finals_muneutrino = remove_duplicates(&m_boson_muonNeutrino_candidates, m_all_particle_candidates);
My question is:
Would m_all_particle_candidates which is
vector<Particle*> m_all_particle_candidates;
be different in each call of remove_duplicates?
I think I am trying to ask is the iterator lepton_finder erased from the vector and not the actual object Particle since I have passed by value?
Note: There was a typo in the remove_duplicate function. I passed by pointer and not value. it should be value
I'm a little confused about what you are saying about passing by value and passing by reference, so I'm going to give a short explanation on that first:
When passing by value, the variable that the method is called with remains unchanged (since a copy is passed into the called method). Be careful though, this case can also incur a heavy performance penalty, since the whole variable is copied! In case of a vector holding many elements this might take quite some time! Passing by value is achieved like this in C++:
When passing by reference (or more or less equivalently by pointer) the outer variable is also changed - since you're only passing a reference into the method, which is referencing the same actual space in memory as the original variable!
So basically what the difference is that in when using call by value, the original caller's value remains unchanged, while when using call by reference, a reference to the original caller's value is passed in, and therefore this value can change on both ends.
Now which method is needed simply depends on what you want to achieve. Pass by Value if the variable you're passing into the method should remain unchanged (m_all_particle_candidates in your example). Or if you need it to change, then pass by reference/pointer.
If the passed-in variable shouldn't change, but you also only need a read-only version of the variable inside the method, then the possible performance problems introduced by passing by value can be overcome by using a const reference. In you case, however, you seem to need a full copy (meaning a normal pass-by-value).
Does the code presented in the OP compile? I don't think so. In fairness, it should be passed through a compiler before posting.
typedef struct {
long double x, y, z;
} V3;
void fnExpectingPtrToVec(vector<V3> * pvec) {
}
void fnExpectingVec(vector<V3> vec) {
}
void testVecs() {
vector<V3> v;
//fnExpectingPtrToVec(v); Does not compile
fnExpectingPtrToVec(&v);
fnExpectingVec(v);
}
If it is expecting a pointer to a vector in the 2nd param, and you passed in a vector instead, then its a compile error.
When you fix the function to accept a vector, not a pointer to one, and call it with your vector it will make a copy and the repeated calls to the function will leave m_all_particle_candidates unchanged.
You're not passing the vector by value.
vector<Boson*>* BosonMaker::remove_duplicates(vector<Boson*>* boson_candidates, vector<Particle*> *child_candidates);
will pass a pointer to the vector by value. But the pointer, which is a copy of the original one, will point to the same vector as the original.
So you're basically changing the same vector as outside the call.
To pass by value, you need:
vector<Boson*>* BosonMaker::remove_duplicates(vector<Boson*> boson_candidates, vector<Particle*> child_candidates);
But be careful when doing so. Copying will occur, so you probably need to override the virtual destructor, copy constructor and assignment operator for Boson and Particle if they're not POD types.

Accessing a Class Function when the Class instance is within a Struct

I have an array of structs -
struct MagicalUnicornBullets {
PS2Sprite SparklyUnicornBullet();
bool onscreen;
};
MagicalUnicornBullets MagicalUnicornBullets[25];
I want to loop through the array, and initialise the contents of the struct.
Obviously, this is just the case of a for loop, and for the bool it's simply onscreen = false; but how would I initialise the SparklyUnicornBullet?
Right now my code is -
MagicalUnicornBullets[i].SparklyUnicornBullet.ScaleAbsolute(4,4);
I'm well aware this is wrong - but how do I access the class functions when they're within the Struct?
Realize that SparklyUnicornBullet is actually a member function which returns a PS2Sprite object. This returned PS2Sprite has a member function ScaleAbsolute which you want to call. So your code above is nearly correct. You are simply missing ()'s:
MagicalUnicornBullets[i].SparklyUnicornBullet().ScaleAbsolute(4,4);
That said, there's a number of things that's bad with your code. For one, you are declaring an array that has the same name as an object:
MagicalUnicornBullets MagicalUnicornBullets[25];
I think this is allowed, but it is so evil and malmotivated that I can't even say that for certian, because I would reject any such code regardless of it's motivation or legality. You should give the array a different name:
MagicalUnicornBullets bullets[25];
Next, your initialization loop is unneeded. The code:
MagicalUnicornBullets MagicalUnicornBullets[25];
creates a C-style array of 25 MagicalUnicornBullets by calling each one's default constructor. So the easiest thing to do is to simply provide a default constructor that does what you want:
struct MagicalUnicornBullets {
MagicalUnicornBullets();
// ...
};
MagicalUnicornBullets::MagicalUnicornBullets()
: onscreen(false)
{
SparklyUnicornBullet().ScaleAbsolute(4,4)
}
Now there's no need for a loop at all. All 25 will be constructed and initialized the way you want.
Finally, usually in C++ it's advantagerous to not use a C-style array at all, but a collection class such as std::vector.