Initialize Variables as Empty - c++

When I have an unsigned int, but I want to find out if it is empty or not, but I need 0, I always declare it as an int and set it to -1. What am I supposed to do, though, when I need the full number spectrum or I am even working with float/double?
With some data-types it is simple, for example std::string which you can just compare to "", but is there a function to check if a variable is empty regardless of data-type, even of custom class objects?

The semantics of a value being missing are exactly why std::optional was introduced to the C++ language specification.
std::optional<unsigned int> value; // by default, the value is missing
if(value) {
// executed if the value is present, it is not
} else {
// this code is executed
}
value = 1;
if(value) {
// This code would now be executed
std::cout << "the value: " << *value << std::endl;
}
This requires a change in thinking regarding the meaning of the variable, but it forces you to think at all times regarding whether or not the variable would be present.
So for example, if you had your own class type MyClass and you wanted to retain a, potentially missing, instance of it, you would do so as follows:
std::optional<MyClass> obj; // Initially missing
obj = MyClass(); // Assigns a newly-created instance of MyClass
obj->foo(); // Calls the 'MyClass::foo' method
obj.reset(); // clears the 'obj' optional

Related

Polymorphism in mixin classes - virtual functions

I'm currently reading about mixin classes and I think I unerstand everything more or less. The only thing I don't understand is why I don't need virtual functions anymore. (See here and here)
E.g. greatwolf writes in his answer here that virtual functions are not needed. Here is the example: (I just copied the essential parts)
struct Number
{
typedef int value_type;
int n;
void set(int v) { n = v; }
int get() const { return n; }
};
template <typename BASE, typename T = typename BASE::value_type>
struct Undoable : public BASE
{
typedef T value_type;
T before;
void set(T v) { before = BASE::get(); BASE::set(v); }
void undo() { BASE::set(before); }
};
typedef Undoable<Number> UndoableNumber;
int main()
{
UndoableNumber mynum;
mynum.set(42); mynum.set(84);
cout << mynum.get() << '\n'; // 84
mynum.undo();
cout << mynum.get() << '\n'; // 42
}
But what happens now if I do something like this:
void foo(Number *n)
{
n->set(84); //Which function is called here?
}
int main()
{
UndoableNumber mynum;
mynum.set(42);
foo(&mynum);
mynum.undo();
cout << mynum.get() << '\n'; // 42 ???
}
What value does mynum have and why? Does the polymorphism work in foo()?!?
n->set(84); //Which function is called here?
Number::set will be called here.
Does the polymorphism work in foo()?!?
No, without virtual. If you try the code, you'll get an unspecified value because before doesn't be set at all.
LIVE
I compiled your code in VS 2013, and it gives an unspecified number.
You got no constructor in your struct, which means that the variable before is not initialized.
Your code example invokes undefined behaviour, because you try to read from the int variable n while it is not in a valid status. The question is not what value will be printed. Your program is not required to print anything, or do anything that makes sense, although you are likely using a machine on which the undefined behaviour will only present itself as a seeminly random value in n or on which it will mostly appear as 0.
Your compiler likely gives you an important hint if you allow it to detect such problems, for example:
34:21: warning: 'mynum.Number::n' is used uninitialized in this function [-Wuninitialized]
However, the undefined behaviour starts even before that. Here's how it happens, step by step:
UndoableNumber mynum;
This also creates the Number sub-object with an unintialised n. That n is of type int and can thus have its individual bits set to a so-called trap representation.
mynum.set(42);
This calls the derived-class set function. Inside of set, an attempt is made to set the before member variable to the uninitialised n value with the possible trap representation:
void set(T v) { before = BASE::get(); BASE::set(v); }
But you cannot safely do that. The before = BASE::get() part is already wrong, because Base::get() copies the int with the possible trap representation. This is already undefined behaviour.
Which means that from this point on, C++ as a programming language no longer defines what will happen. Reasoning about the rest of your program is moot.
Still, let's assume for a moment that the copy would be fine. What else would happen afterwards?
Base::set is called, setting n to a valid value. before remains in its previous invalid status.
Now foo is called:
void foo(Number *n)
{
n->set(84); //Which function is called here?
}
The base-class set is called because n is of type Number* and set is non-virtual.
set happily sets the n member variable to 84. The derived-class before remains invalid.
Now the undo function is called and does the following:
BASE::set(before);
After this assignment, n is no longer 84 but is set to the invalid before value.
And finally...
cout << mynum.get() << '\n';
get returns the invalid value. You try to print it. This will yield unspecified results even on a machine which does not have trap representation for ints (you are very likely using such a machine).
Conclusion:
C++ as a language does not define what your program does. It may print something, print nothing, crash or do whatever it feels like, all because you copy an unininitialised int.
In practice, crashing or doing whatever it feels like is unlikely on a typical end-user machine, but it's still undefined what will be printed.
If you want your derived-class set to be called when invoked on a Number*, then you must make set a virtual function in Number.

How to change value of an object from a function in c++?

Scenario
I am in the process of learning C++, so please forgive my naivety. I have attempted to build my own class, objects and methods - each of which seem to work as expected. However I am running into issues with what seems to be uninitialized storage (and possibly the use of local objects?) however I would like to know how to fix it, if indeed it is meant to be, or an alternative. My current train of thought is that the object needs to be passed...however that could be way off...
Code
//header
class Car{
public:
USHORT GetMin();
void SetMin(USHORT min);
private:
USHORT itsMinPrice;
};
USHORT Car::GetMin(){
return itsMinPrice;
}
void Car::SetMin(USHORT min){
itsMinPrice = min;
}
-
void StartingPrices(){
Car Mercedes;
std::cout << Mercedes.GetMin() << "\n";
Mercedes.SetMin(50);
std::cout << Mercedes.GetMin()<< "\n";
}
int main(){
float input;
Car Mercedes;
Mercedes.SetMin(100);
StartingPrices();
std::cout << Mercedes.GetMin() << "\n";
std::cin >> input;
return 0;
}
Expected output
100, 50, 50
Actual output
debug win32 - 52428, 50, 100
release win32 - 0, 50, 100
In your StartingPrices function, the Mercedes object you call GetMin is created on the line before, i.e., not the same object as the one you create in the main function.
That means that the object do not yet have itsMinPrice set to anything, hence the value will be garbage (that is, a value which you don't really have control over), in this case 52428 in debug and 0 in release.
What I think you wish to do is pass a reference of the Mercedes object from the main function into the StartingPrices function:
void StartingPrices(Car& mercedes){
std::cout << Mercedes.GetMin() << "\n"; // Here the GetMin method will return 100.
...
}
int main(){
....
Car Mercedes;
Mercedes.SetMin(100);
StartingPrices(Mercedes);
....
}
Its also a good idea to set the default value of the members in the constructor of the class.
In your Car class you do not initialize your member variable itsMinPrice except when you call SetMin, this means there is a risk that you will use an uninitialized Car instance if you forget to call SetMin on it. Normally it is good to have initialization in a constructor of the class with some value e.g.
Car() : itsMinPrice(0) {
}
or create a constructor that takes an initial value
Car(USHORT minValue) : itsMinPrice(minValue) {
}

dynamic bitset initialized and called from other method gives segmentation fault

I initialize a dynamic bitset in a constructor of a class and then call a method of that class to fill it with some values. I get a segmentation fault no matter which part of the bitset I try to access.
MyClass::MyClass()
{
boost::dynamic_bitset<> occupancy(200000); // all 0's by default
std::cout << occupancy.size() << "\n";
std::cout << occupancy[1234] << "\n";
fill_occupancy();
}
void MyClass::fill_occupancy()
{
std::cout << occupancy[1234] << "\n";
}
The constructor prints out the correct output of 200000 and 0, but when enters the fill_occupancy methood it gives segfault.
I checked this question, but I don't think that applies, bc I construct the bitset properly as I see the correct output from the constructor.
I've found a way to make it work if I simply make the method fill_occupancy() to accept argument of type dynamic_bitset<> and then call it with fill_occupancy(occupancy). Why this works and the code above does not? Other data types I can call in other methods without having them as argument.
Thank you.
Edit
This is in case someone would be interested in more detailed explanation:
class MyClass()
{
boost::dynamic_bitset<> occupancy; //calls default bitset constructor (i.e size 0)
}
In the MyClass constructor, calling just
MyClass::MyClass()
{
occupancy(200000); // this is WRONG
}
produces error as the occupancy is set to zero size. To resize it one has to call
MyClass::MyClass()
{
occupancy.resize(200000); // this is CORRECT
}
Then occupancy has the correct size and is member of MyClass and as such can be accessed from any other method of the class such as fill_occupancy().
My original construction made the occupancy a local variable of the same name as the member one so in the constructor it worked but everywhere else the member (of size 0) was called which explains the segfault.
Thank again juanchopanza for explanations.
The constructor is instantiating a local bitset called occupancy, not a data member of the same name:
boost::dynamic_bitset<> occupancy(200000); // local variable
It seems like you want to initialize a data member, which you can do like this:
MyClass::MyClass(): occupancy(200000)
{
std::cout << occupancy.size() << "\n";
std::cout << occupancy[1234] << "\n";
fill_occupancy();
}
In your code, "occupancy" is a locale Variable, so you should not access it in the outside.

std::cout of string not working

I have a class State that has a string data type called moveType. In the implementation of my code, I am calling a setter void setMoveType(string _moveType); and it's implemented with just moveType = _moveType;
When I call my getter string getMoveType() const; on an instance of State and output it to cout, nothing is displayed.
I am couting upon entering the getMoveType() function. The parameter indeed has the correct value, but it appears that it's not getting set at all.
Does anyone have any idea? I feel this is something simple/trivial in c++ that I'm just completely forgetting.
string State::getMoveType() const {
return moveType;
}
void State::setMoveType(string move_type) {
cout << "In setMoveType and param = " << move_type << endl;
moveType = move_type;
}
std::cout << vec_possibleSuccessors[i].getMoveType() << endl; // within loop;
vector<State> vec_possibleSuccessors;
if (_minState.canMoveUp()) {
up = _minState.moveUp();
up.setMoveType("UP");
up.setF(f(up));
vec_possibleSuccessors.push_back(up);
}
In the above code, _minState and up are instances of State. Also, I have made sure that my copy constructor and assignment operator have been modified to include moveType assignments.
There isn't really enough code to know for sure, but I have a guess: Either you actually assigned to a shadowed variable in the "set" function and never set the class attribute at all, or your State object has actually been destroyed and the string becomes empty (since being empty is one possible option when using destroyed memory).
Well not an answer but a short example that works the way you seem to intend this to work:
#include <string>
class State
{
private:
std::string m_moveType;
public:
State() : m_moveType( "unknown" ) {}
std::string getMoveType() const { return m_moveType; }
void setMoveType( const std::string& moveType ) { m_moveType = moveType; }
};
In your main function or were else you need a vector of States you could write this:
#include <iostream>
#include <vector>
#include "State.h"
int main()
{
std::vector< State > states;
for( int i=0; i<10; ++i )
{
State newState;
newState.setMoveType( "state" );
states.push_back( newState );
}
// do whatever you need to do....
std::vector< State >::iterator it;
std::vector< State >::iterator end = states.end();
for( it=states.begin(); it != end; ++it )
std::cout << (*it).getMoveType() << std::endl;
return 0;
}
A few remarks:
passing parameters by value like setMoveType( string s ) is not
adviseable, pass const references instead. Passing by value incurrs a
full copy of the passed object
be careful with includes and namespaces, in doubt take the extra time
to type std::... if you intend to use a feature defined in namespace
std, and never type using namespace std in a header file.
initialize private members to a sensible default and do it in the class
initializer list
I'm not sure on this either, but you appear to be storing this State in a vector. Could you post the code to how you set elements in the vector? Its important to note that you can't update an element in a vector once its inserted (unless you store a pointer to the element). Also depending upon how you call set, there may be problems.

std::map losing track of my data?

I'm sticking some data, wrapped with boost::any into a map in a class method getValue. Everything works fine, the data is in the map as appropriate etc etc in getValue. The second I leave getValue and try to use this data, it's no longer in the map.
This has me stumped, I'm probably forgetting to use a reference at a key spot, but I can't find it.
The relevant code is as follows:
test.c
//We don't want to actually document the timer, the user can do that if he wants to.
timeval tmp;
tmp.tv_sec = 0;
tmp.tv_usec = 0;
gettimeofday(&tmp, NULL);
getValue<timeval>(timerName) = tmp;
std::cout << tmp.tv_usec << " : " << getSingleton().globalValues.count(key) << std::endl; //Count returns 0 here, for a given key X_X
test.h
/* Grab the value of type T found while parsing. Should use checkValue first.*/
template<typename T>
static T& getValue(const char* identifier) {
//Used to ensure we have a valid value
T tmp;
//Used to index into the globalValues map
std::string key = std::string(identifier);
std::map<std::string, boost::any>& gmap = getSingleton().globalValues;
if(checkValue(identifier)) //If we have the option, set it's value
tmp = getSingleton().vmap[identifier].as<T>(); //vmap is correct, it specifies default values passed in via command line.
//We may have whatever is on the commandline, but what if
//The programmer has made modifications?
if(!gmap.count(key)) //The programmer hasn't done anything, lets register it then
gmap[key] = boost::any(tmp);
std::cout << "gmap " << key << std::endl;
std::cout << getSingleton().globalValues.count(key) << std::endl; //count returns 1 here, for a given key.
return boost::any_cast<T&>(gmap[key]);
}
...
test.h
//Map of global values, stored here instead of in OptionsHierarchy
//For ease of implementation
std::map<std::string, boost::any> globalValues;
On these lines you use vmap instead of gmap. Is that right?
if(checkValue(identifier)) //If we have the option, set it's value
tmp = getSingleton().vmap[identifier].as<T>();
Also I noticed that you're using count to check for existence of an item. Generally speaking unless you actually need the count, that will result in doing more work than find although for std::map it may be smart enough to optimize count into find. Since you want to insert if it doesn't exist and no-op when it does, just use insert as that's exactly the behavior insert will give you.
I fixed this, note how I define key in getValue as being std::string(identifier). In test.c I was defining key as sanitizeString(..) which returned a different key, obviously. Of course you guys couldn't see that so my bad.