How to make a static map in c++? - c++

I am working on 2 files, lets take file1.cpp and file2.cpp.
file1.cpp contains:
//File 1
#include <iostream>
#include <map>
struct category {
int id;
};
void fun();
std::map<char, category> mymap1;
static std::map<char, category> mymap;
std::map<char, category>::iterator map_iter;
std::map<char, category>::iterator map_iter1;
int main ()
{
mymap1['a'] = {20};
mymap1['b'] = {30};
mymap1['c'] = {40};
for(int i = 0;i < 4; i++)
fun();
return 0;
}
//File 2
#include<file2.h>
void fun()
{
mymap = mymap1;
map_iter = mymap.begin();
for (map_iter1 = mymap1.begin(); map_iter1 != mymap1.end();++map_iter1)
{
map_iter->second.id = map_iter1->second.id - map_iter->second.id;
std::cout<<map_iter1->second.id<<" " <<map_iter->second.id;
map_iter->second.id=map_iter1->second.id;
++map_iter;
}
}
I am trying to initialize mymap once when for loop run for the first time after that initialization should not happen as it happen in static variable.
But this behaviour is not shown and each time mymap is getting initialize.
I don't want the "id" getting initialize every time.
How to work?

Create a function that returns a static map
static std::map<char, category> maps() {
static std::map<char, category> m;
//...
return m;
}

If I understand your question correctly, you should be checking before assigning anything to mymap in your fun() function if you only want to initialize it once.
For example, you could pass a variable by reference in your function by adding a parameter, let's call it foo. You initialize it to 0 before your for loop, add a check in your function to make sure that foo == 0 and increment it at the end.

in general 'initialize once' is done like:
void foo()
{
static bool first = true;
if( first )
{
first = false;
// first time init here
}
// rest of func here
}
Also a note on what static means:
static on a global variable:
* only accessible in local translation unit
static on a function:
* only accessible in local translation unit
static on a local variable:
* persists through calls, only one instance even on multiple/recursive call
static on a class/struct member:
* only one instance, regardless of number of parent objects

Related

C++ global variable that can be changed only in one method, possible?

I'm looking for a way to have an int variable that persists value across method calls. From this perspective a class member will be good.
But I would like that int variable to be changed in only one particular method.
How do I make that?
I tough about
void MyClass::my_method(){
static int var = 0;
var++;
}
But, I would like var = 0; to be executed only the first time.
void my_method(){
static int var;
var++;
}
The problem here is, that
static int var;
is only visible in the local scope of my_method().
You can make it global just by definition of that variable outside of my_method():
int var;
void my_method() {
var++;
}
but var will be visible for everyone.
The better way is to encapsulate all of that into a class:
class MyClass {
public:
static void my_method() {
var++;
}
private:
static int var = 0;
};
You can use the following key access pattern:
struct Foo {
void fun1();
void fun2();
static class Var {
friend void Foo::fun1();
int i = 0;
public:
int value() const { return i; }
} var;
};
Foo::Var Foo::var;
void Foo::fun1() { var.i = 42; }
void Foo::fun2() {
// var.i = 42; // this will generate compile error cause fun2 doesn't have to var
}
Live Demo
This way only the member functions of Foo that are declared friends in wrapper class Var can change its private member variables (e.g., var.i).
var is just locally, if you want that to be 0 the first time the function returns make it initialized to -1 or if 0 is just right you are ok. As is var is only visible inside my_method so if you want that to be visible to all the class you have to put it outside and use only my_method to modify the value.
I don't have enough rep to comment yet, But you should note that Static is not equal to Constant.
Static variables maintain their value for ALL instances of a class, whereas Constant variables can have different values for each instance (object) of a class.
See this question for a more in-depth explanation.
What is the difference between a static and const variable?
To answer your question directly, you cannot have a true "Global" vairable that is only editable from one class. Instead, you should consider πάντα ῥεῖ 's answer OR wait to declare the constant until after you know the value you would like to assign to it. For instance, I want to store X+10 to a constant variable Y
int x = 5 //create variable
//Do whatever you need to do to get the value
function myFunction(){
x = x + 10;
}
const int y = x; //now Y = 15 and cannot be changed.

Is it possible to access a variable in a sketch from a class (Arduino)?

Say I want to get a value of a variable in a sketch from a class I wrote like
sketch
int device;
void setUp() {
device = 1;
}
And I have a class
SomeClass.cpp
void Device::checkTimedEvent() {
someDevice = device; //variable from sketch
}
I know it's possible to access members from another class where I can include the class and use the :: scope operator but not sure how the sketch relates to classes.
thanks
It appears that the usual C/C++ "extern" syntax works in Arduino as if the sketch file were a .cpp file:
Sketch:
int device = 123;
SomeClass.cpp:
extern int device;
void SomeClass::checkTimedEvent() {
someDevice = device; // variable from sketch
// will display "123" (or current value of device)
// if serial output has been set up:
Serial.println("device: " + String(device));
}
You may need to worry about startup and initialization order, depending on the complexity of your project.
class Test
{
public:
int N = 0;
};
Test t;
int someNumber = t.N;
The best way to do this is to pass the value into the function as a parameter. Here's a simple example:
Class:
class Test
{
public:
void doSomething(int v);
private:
int myValue;
};
void Test::doSomething(int v)
{
myValue = v;
}
Sketch:
Test t;
int someNumber;
void setup()
{
someNumber = 27;
t.doSomething(someNumber);
}
The setup() function here passes global variable someNumber into the class's member function. Inside the member function, it stores its own copy of the number.
It's important to note that it has a completely independent copy of the number. If the global variable changes, you'd need to pass it in again.
As much as Bloomfiled's answer is correct using the the more accepted practice of employing Getter and Setter functions. Below demonstrates this along with making the attribute public and directly accessing it.
class Test
{
public:
void SetMyValue(int v);
int GetPublicValue();
int GetPrivateValue();
int myPublicValue;
private:
int myPrivateValue;
};
void Test::SetMyValue(int v)
{
myPublicValue = v;
myPrivateValue = v;
}
int Test::GetPublicValue()
{
return myPublicValue;
}
int Test::GetPrivateValue()
{
return myPrivateValue;
}
Test t;
int someNumber;
void setup()
{
someNumber = 27;
t.SetMyValue(someNumber); // set both private and public via Setter Function
t.myPublicValue = someNumber; // set public attribute directly.
someNumber = t.GetPublicValue(); // read via Getter
someNumber = t.GetPrivateValue();
someNumber = t.myPublicValue; // read attribute directly
}
void loop() {
// put your main code here, to run repeatedly:
}

C++: std::map<int,int> crashes when being assigned

I'm trying to make an int to int map but the program crashes and I don't realize why.
I've summarized the problem to this short simple code.
When the program starts, since the Utilities member _instance is static- it initialize it, by going to its constructor, which contain a single line: An int to int (simple) map assignment. but then it crashes.
Notice that if I comment that line, the program doesn't crash,
and that the main contains that very same line.
So my two questions are:
1) Why does it crash? is there a point behind this behavior?
2) How do I fix it so I can initialize the map at constructor?
Thank You
#include <map>
class Utilities
{
public:
~Utilities(){};
static Utilities& instance();
private:
Utilities();
Utilities( const Utilities& ){};
static Utilities _instance;
static std::map<int, int> textIntToIntMap;
};
Utilities Utilities::_instance = Utilities();
std::map<int, int> Utilities::textIntToIntMap;
Utilities::Utilities()
{
//The following line crashes, why?
textIntToIntMap[1] = 2;
}
int main()
{
static std::map<int, int> text2;
text2[4] = 2;
int xxx = 3;
}
You have an initialization order problem:
Utilities Utilities::_instance = Utilities();
This line calls the default constructor of Utilities, which then tries to populate the map. But the map is not initialized at this stage.
You should design your code to be robust against such initialization order issues. You can mitigate some of that by creating static instances inside functions. This gives you a handle on the ordering of initializations. But a simple re-ordering of the definitions should fix the immediate problem:
std::map<int, int> Utilities::textIntToIntMap;
Utilities Utilities::_instance = Utilities(); // OK, map has been defined
The issue is that you call the Utilities constructor before Utilities::textIntToIntMap has been constructed.
Swap the order of the following two lines:
Utilities Utilities::_instance = Utilities();
std::map<int, int> Utilities::textIntToIntMap;
Before initializing _instance you need to define map textIntToIntMap outside the class. Because in constructor you are using textIntToIntMap which is a static member so you need to define it first. So outside the class use following lines:
std::map<int, int> Utilities::textIntToIntMap;
Utilities Utilities::_instance = Utilities();
Others have already caught that the Utilities() are constructed before Utilities::textToIntMap. So, now the question is: how to avoid such problems in the future?
You can use a function returning a reference to a static local variable to ensure that the construction is done before the reference is used. You can put such function into a namespace. You should also have a convenience typedef with hopefully a shorter name, so that declaring iterators is not a finger-breaker on C++98. On C++11 you should be using auto anyway.
Note that the use of global or function-static non-POD data is not thread-safe in C++98. If you wish to safely use textToMap() from multiple threads, with no guarantee that it was accessed before the 2nd thread was started, textToIntMap would need to wrap the initialization within a mutex. To get a rough idea how this might be done, see the inner function from Qt's convenient Q_GLOBAL_STATIC.
The use of a singleton class seems like a pointless Java-ism in this case.
Run a test on ideone.
// Utilities.h
namespace Utilities {
typedef std::map<int, int> Map;
Map & textToIntMap();
}
// Utilities.cpp
namespace Utilities {
namespace {
struct InitializedMap : Map {
InitializedMap() {
insert(value_type(1, 2));
// or
(*this)[1] = 2;
}
};
}
Map & textToIntMap() {
static InitializedMap map;
return map;
}
}
Try this way::
#include <map>
#include <iostream>
using namespace std;
class Utilities
{
public:
static Utilities& instance() {
static Utilities instance;
return instance;
}
~Utilities(){};
void PrintMapValues();
void AddKeyValue(int key, int value);
private:
Utilities();
Utilities( const Utilities& ){};
std::map<int, int> int_to_int_map_;
};
Utilities::Utilities()
{
//The following line crashes, why?
int_to_int_map_[-99] = 2;
}
void Utilities::PrintMapValues() {
for(std::map<int, int>::iterator it = int_to_int_map_.begin(); it != int_to_int_map_.end(); ++it){
cout << "Key:" << it->first << " Val:" << it->second << endl;
}
}
void Utilities::AddKeyValue(int key, int value) {
int_to_int_map_[key] = value;
}
int main()
{
Utilities& utils = Utilities::instance();
for (int i=0; i< 10; i++) {
utils.AddKeyValue(i, i+20);
}
utils.PrintMapValues();
return 0;
}

C++ Assign a const value at run-time?

I have a constant value that never changes during run-time, but is impossible to know until run-time.
Is there a way to declare a constant (either as a member of a class or not) without defining it and also assign a computed value once (and only once) it is determined; or am I going to have to resort to a non-const declaration and use coding S & Ps (ALL_CAPS variables names, static declaration if in a class, etc.) to try and keep it from changing?
CLARIFICATION:
Though these are good answers, the real-world situation I have is more complicated:
The program has a main loop that continually runs between processing and rendering; the user can set required options and once they are set they will never change until the program is restart. An "Initialize" function is set up for anything that can be determined before the main loop, but values that are dependent on user interaction must be performed in the middle of the loop during the processing phase. (At the moment, persistent data storage techniques come to mind...)
Something like this?
const int x = calcConstant();
If it's a class member, then use the constructor initialisation list, as in Yuushi's answer.
You can define it in a struct or class and utilize an initialisation list:
#include <iostream>
struct has_const_member
{
const int x;
has_const_member(int x_)
: x(x_)
{ }
};
int main()
{
int foo = 0;
std::cin >> foo;
has_const_member h(foo);
std::cout << h.x << "\n";
return 0;
}
As a static or function-local variable:
const int x = calcConstant();
As a class member:
struct ConstContainer {
ConstContainer(int x) : x(x) {}
const int x;
};
Yes, you can make a private static singleton field with an initialization method and a gettor method. Here's an example of how to do it:
// In foo.h
class Foo
{
public:
// Caller must ensure that initializeGlobalValue
// was already called.
static int getGlobalValue() {
if (!initialized) {
... handle the error ...
}
return global_value;
}
static void initializeGlobalValue(...)
private:
static bool initialized;
static int global_value;
};
// In foo.cpp
bool Foo::initialized = false;
int Foo::global_value;
void Foo::initializeGlobalValue(...) {
if (initialized) {
...handle the error...
}
global_value = ...;
initialized = true;
}

C++ -- how to initialize the static variable inside a member function?

void ClassA::Func()
{
static map<int, string> mapIntStr;
mapIntStr[0] = m_memberVariable0; <= just want to do once & m_memberVariable* are not static
mapIntStr[1] = m_memberVariable1; <= just want to do once
...
}
I want to ONLY initialize the variable mapIntStr once. As we know, we can put the initialize code inside a static function and call that static function and store the return value into mapIntStr.
Here I would like to get a quick & dirty solution. As I remember, there is something called static scope. I would like to initialize mapIntStr ONCE without calling a static function. how can I do it?
Thank you
void ClassA::Func()
{
static map<int, string> mapIntStr;
if(mapIntStr.empty()){
mapIntStr[0] = m_memberVariable0;
mapIntStr[1] = m_memberVariable1;
// ...
}
}
How about that? :)
Edit
Well, the best solution would be to take the mapIntStr out of the function and into the class. And then you won't get around the static function call.
//in ClassA.h
class ClassA{
public:
void Func();
static map<int,string> InitStatic();
static map<int,string> mapIntStr;
};
//in ClassA.cpp
#include "ClassA.h"
void ClassA::Func(){
// use mapIntStr
}
map<int,string> ClassA::InitStatic(){
map<int,string> ret;
// init ret
return ret;
}
map<int,string> ClassA::mapIntStr = ClassA::InitStatic();
That're about the only options that I know of. So you've got the choice. Initialize the map once in the func or even in a contructor the first time a ClassA object is created (better version of the two) and live with the overhead of a nearly noop call to empty(), which will most likely be a single instruction only after proper inlining and will impose no overhead whatsoever, or use a static initialization function.
Create a inside struct, then initialize everything in the constructor of that struct, and then you declare a static variable of that struct.
void fun()
{
struct setter
{
setter(){}
};
static setter setup;
}
For your case:
void ClassA::Func()
{
struct Map : public std::map<int, string>
{
Map()
{
(*this)[0] = something;
(*this)[1] = somethingElse;
}
}
static Map map;
}