class FruitClass (SOLVED) - page 2

 
JC:

I haven't got anything backwards. I'm not the author of the piece linked to at stackoverflow.com.

What I am saying is the following:

  • With #property strict, global variables are always initialized to zero in MQL4 in all instances I have seen, but I have MQL5 code where this is not the case.
  • There is no reason why MQL4/5 should necessarily choose to follow the C++ standard; it doesn't do so in all cases; and learning MQL4/5 from C++ resources such as www.learncpp.com, above, could potentially be misleading.

I have nowhere said that MQL4 initialises local or member variables when #property strict is defined. I am saying that MQL4/5 is not C++, and could [choose|have chosen] to diverge from the C++ standard in this area.


I know from painful experience that (at least) the class members are not initialized in MT4. 

 
nicholishen:

I know from painful experience that (at least) the class members are not initialized in MT4. 


From my experience most coders initialise variables and members immediately after their declaration, regardless of the programming language specification. It is cheap, and resistant to future specification changes.

 

Hello everyone,

I am thinking of starting my next indiClass.mqh.  Something to do this (Code not completed yet).

//+------------------------------------------------------------------+
//|   Find out Some Basic information                                |
//+------------------------------------------------------------------+
double FIRST_BASICS()
  {
   double Selection_1=0,OrderAsk=MarketInfo(NULL,MODE_ASK),OrderBid=MarketInfo(NULL,MODE_BID);
   return(Selection_1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double SECOND_BASICS()
  {
   double Selection_2=0,HIGH=MarketInfo(NULL,MODE_HIGH),LOW=MarketInfo(NULL,MODE_LOW);
   return(HIGH);return(LOW);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double THIRD_BASICS()
  {
   double Selection_3=0,Spread=MarketInfo(NULL,MODE_SPREAD);
   return(Selection_3);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string STOCHSIGNAL()
  {
   double StochSignal=iStochastic(NULL,TIMEFRAME,SIGNAL,MAIN,Slowing,MODE_EMA,0,MODE_SIGNAL,0);
   SS=DoubleToString(StochSignal,0);
   return(SS);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string STOCHMAIN()
  {
   double StochMain=iStochastic(NULL,TIMEFRAME,SIGNAL,MAIN,Slowing,MODE_EMA,0,MODE_MAIN,0);
   SM=DoubleToString(StochMain,0);
   return(SM);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string READPLUS()
  {
   double READplus=iADX(NULL,TIMEFRAME,8,PRICE_CLOSE,MODE_PLUSDI,0);
   RP=DoubleToString(READplus,0);
   return(RP);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string READMINUS()
  {
   double READminus=iADX(NULL,TIMEFRAME,8,PRICE_CLOSE,MODE_MINUSDI,0);
   RM=DoubleToString(READminus,0);
   return(RM);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string CURRENTADX()
  {
   double CurrentADX=iADX(NULL,TIMEFRAME,8,PRICE_CLOSE,MODE_MAIN,0);
   AM=DoubleToString(CurrentADX,0);
   return(AM);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string CURRENTRSI()
  {
   double CurrentRSI=iRSI(NULL,TIMEFRAME,8,PRICE_CLOSE,0);
   RSI=DoubleToString(CurrentRSI,0);
   return(RSI);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string EMIMA()
  {
   double EM_iMA=iMA(NULL,TIMEFRAME,8,0,MODE_EMA,PRICE_CLOSE,0);
   EMiMA=DoubleToString(EM_iMA,5);
   return(EMiMA);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string SMMMA()
  {
   double SMM_MA=iMA(NULL,TIMEFRAME,8,0,MODE_SMMA,PRICE_CLOSE,0);
   SMmMA=DoubleToString(SMM_MA,5);
   return(SMmMA);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string LWMA()
  {
   double LW_MA=iMA(NULL,TIMEFRAME,8,0,MODE_LWMA,PRICE_CLOSE,0);
   LWMA=DoubleToString(LW_MA,5);
   return(LWMA);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string SMMA()
  {
   double SM_MA=iMA(NULL,TIMEFRAME,8,0,MODE_SMA,PRICE_CLOSE,0);
   SMMA=DoubleToString(SM_MA,5);
   return(SMMA);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string MONEYFLOW()
  {
   double iMoneyFlow=iMFI(NULL,TIMEFRAME,8,0);
   MF=DoubleToString(iMoneyFlow,0);
   return(MF);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string MACD_MAIN()
  {
   double IMACD_main=iMACD(NULL,TIMEFRAME,12,26,9,PRICE_OPEN,MODE_MAIN,0);
   macd_main=DoubleToString(IMACD_main,20);
   return(macd_main);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string MACD_SIGNAL()
  {
   double IMACD_signal=iMACD(NULL,TIMEFRAME,12,26,9,PRICE_OPEN,MODE_SIGNAL,0);
   macd_signal=DoubleToString(IMACD_signal,20);
   return(macd_signal);
  }
//-------------------------------------------------------------------------+
 
GrumpyDuckMan:

Hello everyone,

I am thinking of starting my next indiClass.mqh.  Something to do this (Code not completed yet).


Perhaps you should start the lessons on how functions work first... 

 
JC:

I haven't got anything backwards. I'm not the author of the piece linked to at stackoverflow.com.

What I am saying is the following:

  • With #property strict, global variables are always initialized to zero in MQL4 in all instances I have seen, but I have MQL5 code where this is not the case.
  • There is no reason why MQL4/5 should necessarily choose to follow the C++ standard; it doesn't do so in all cases; and learning MQL4/5 from C++ resources such as www.learncpp.com, above, could potentially be misleading.

I have nowhere said that MQL4 initialises local or member variables when #property strict is defined. I am saying that MQL4/5 is not C++, and could [choose|have chosen] to diverge from the C++ standard in this area.

You are right and I would not rely on any initialization in MT4 either, as similarly to MT5, the documentation specify that variables (without differentiation) are NOT initialized implicitely.

As I already said, if someone already knows C++ that's fine, if he starts programming there is no need to learn C/C++ at all. Though he can do it if he wants of course.

 
nicholishen:

Because the computer assigns it to a memory address that could have garbage in it, but in this case you improperly defined the constructor by adding "void" as it's return type. Contructors do not have a return. In order to avoid these issues make sure your constructor doesn't have a return type and it's also more efficient to initialize your member variables with an initialization list

More efficient ? Could you explain that please, I always thought it was just a "coding-style" without any real impact.
nicholishen:

Don't let it overwhelm you... start out making simple classes that print to the log - and then as you learn you can start applying inheritance to make them more robust.


Could you explain, in simple words please, how using inheritance is making a class more robust ? Thanks.

 
Alain Verleyen:
More efficient ? Could you explain that please, I always thought it was just a "coding-style" without any real impact.

Could you explain, in simple words please, how using inheritance is making a class more robust ? Thanks.


Robust is used in this context as a metaphor and not it's literal translation, and it is more efficient to directly initialize a variable instead of first initializing it and then later assigning it a value.

class a
{
   int num;
public:
   a()
   {
      num = 4;
   }
};

This assigns value after initialization. 

class a
{
   int num;
public:
   a():num(4)
   {
   }
};

This assigns value during initialization.

 

...and of course you would need to initialize const members in the list as well.

class Foo
{
   const double m_pi;
public:
   Foo():m_pi(3.14159){}
};
 
nicholishen:

Robust is used in this context as a metaphor and not it's literal translation, and it is more efficient to directly initialize a variable instead of first initializing it and then later assigning it a value.

This assigns value after initialization. 

This assigns value during initialization.


I'm sorry to tell you but this is not true. C++ and MQL4 don't auto-generate code to initialise member variables that are simple types.

It is only imperative to use initialiser lists when the member variables are other classes.

class Foo
{
public:
   int Num;
public:
   Foo() :
      Num(-1)
   {
   }

   Foo(int num) :
      Num(num)
   {
   }
   //Foo(int num)
   //{
   //   Num = num; // This code is no faster/slower than the previous version (although I would expect the previous version to be the coding standard for most projects)
   //}
};

class Bar
{
public:
   Foo FooVar;
public:
   Bar()
   {
      FooVar.Num = 4; // This is the second time we assign to Num. It was already set to -1 when Foo() ctor was called by the generated initialiser list
   }
};

class Blah
{
public:
   Foo FooVar;
public:
   Blah() :
      FooVar(4) // this is more efficient because it constructs and assigns all at once
   {
   }
}


Also I would like to clear up another misunderstanding in this thread.

In MQL4 there's a difference between heap based objects and stack based objects.

  - MQL4 classes that are created on the heap with the new operator seem to use "calloc" rather than "malloc" under the covers which zero initialises the buffer before use.

  - MQL4 classes that are created on the stack (local variables within functions) do not do this and just map the contents of the current stack onto their structure which are random bytes.

Stack based objects will produce "uninitialized memory reads" (UMR) if the simple instance variables are not set in the ctors.


For performance reasons C++ uses malloc and not calloc so UMR are common with heap as well as stack based objects.

 
nicholishen:

Robust is used in this context as a metaphor and not it's literal translation, and it is more efficient to directly initialize a variable instead of first initializing it and then later assigning it a value.

So you said robust but it's not robust ? I don't understand your metaphor sorry.

This assigns value after initialization. 

This assigns value during initialization.

Maybe, maybe not, not sure where you got this information ?

Anyway I checked and there is no significant difference. However this simple test is probably not the more accurate (I saw difference if you inverse the loops, that's why I made 2 functions).

2017.09.19 00:11:23.504    Efficient EURUSD,M5: 1: standard initialization, 1,000,000,000 iterations done in 102,565,131 µs
2017.09.19 00:09:40.938    Efficient EURUSD,M5: 2: initilization list, 1000000000 iterations done in 102216062 µs
2017.09.19 00:07:58.723    Efficient EURUSD,M5: 2: initilization list, 1000000000 iterations done in 102211334 µs
2017.09.19 00:06:16.511    Efficient EURUSD,M5: 1: standard initialization, 1000000000 iterations done in 104452869 µs

By they way, I run the same code on MT5, and I got inverse results, there standard initialization is faster.

2017.09.19 00:20:26.266    1: standard initialization, 1000000000 iterations done in 75675905 µs
2017.09.19 00:21:45.802    2: initilization list, 1000000000 iterations done in 79535963 µs
2017.09.19 00:23:05.121    2: initilization list, 1000000000 iterations done in 79318647 µs
2017.09.19 00:24:21.583    1: standard initialization, 1000000000 iterations done in 76462546 µs

Also notice that MT5 is faster by more than 25% for such a simple thing.

Files:
Efficient.mq4  7 kb