Questions about OOP - page 3

 
Alain Verleyen #:

This is mainly something for the compiler and hardware. Not something for average MQL coder.

The example in the second video with the double loops is very bad. Unfortunately we can't check the assembler code produce by MQL compiler, but here is the C++ result :

MQL coders don't have much to worry about "branches in your code".

I think the code was not about a real example, but to demonstrate something.

The assembly you have gotten from the compiler was optimized, and removed the branch. That was not the point, it was about to show what happens, if the branch predictions fail, and how costly this is on the CPU level.

But to pu5 this into perspective, if you happen to clear out the pipeline and discard the results of 10 OPs, it would probably be maybe around up to 400 CPU cycles or so. On today's CPUs this would be 0.00000002 seconds. (Discard + reprocess).

But to some extend, doesn't this contradict your statement in this post?

https://www.mql5.com/en/forum/462075/page2#comment_52288061

I mean, there you state even a small improvement compounds quickly.
 
Dominik Egert #:
I think the code was not about a real example, but to demonstrate something.

The assembly you have gotten from the compiler was optimized, and removed the branch. That was not the point, it was about to show what happens, if the branch predictions fail, and how costly this is on the CPU level.

But to pu5 this into perspective, if you happen to clear out the pipeline and discard the results of 10 OPs, it would probably be maybe around up to 400 CPU cycles or so. On today's CPUs this would be 0.00000002 seconds. (Discard + reprocess).

But to some extend, doesn't this contradict your statement in this post?


I mean, there you state even a small improvement compounds quickly.
Please explain us, MQL coders, how you "avoid branches in your code" ? And how it improves performance ?
 
Alain Verleyen #:
Please explain us, MQL coders, how you "avoid branches in your code" ? And how it improves performance ?
Off topic...

For some reason, you derailed this thread a bit.
 
Dominik Egert #:
Off topic...

For some reason, you derailed this thread a bit.
Wow !
 
Thank you very much for your answers, Alain and Dominik. For me personally, the discussion that began with post 11 led to a better understanding of how memory and processor work.
 

Can I expect the default constructors of member objects to be called before the constructor body starts executing?

The following test shows that it works:

struct SOME_STRUCT
  {
   string name;
          SOME_STRUCT() : name("SOME_STRUCT") { Print(__FUNCTION__); }
  };

class SomeClass
  {
public:
   string name;
          SomeClass() : name("SomeClass") { Print(__FUNCTION__); }
  };

class Foo
  {
private:
   SOME_STRUCT member1;
   SomeClass   member2;
public:
               Foo() { PrintFormat(__FUNCTION__ + " member1: %s; member2: %s", member1.name, member2.name); }
  };

void OnStart()
  {
   Foo foo;
  }
/* Execution result
   SOME_STRUCT::SOME_STRUCT
   SomeClass::SomeClass
   Foo::Foo member1: SOME_STRUCT; member2: SomeClass
*/

But can I expect this to work always (I didn't find anything in the documentation about this)?

Or is it better to explicitly call the default constructors for member objects in the initialization list?

class Foo
  {
private:
   SOME_STRUCT member1;
   SomeClass   member2;
public:
               Foo();
  };

Foo::Foo(void) : member1(), member2()
  {
   PrintFormat(__FUNCTION__ + " member1: %s; member2: %s", member1.name, member2.name);
  }

That is, is what I highlighted redundant?

 

Is it necessary to check a pointer before deleting an object?

Here is a typical case of unsuccessful EA initialization

class A
  {
public:
   ~A() { Print(__FUNCTION__); }
  };

class B
  {
public:
   ~B() { Print(__FUNCTION__); }
  };

A* a;
B* b;

int OnInit()
  {
   a = new A;
   if(somethingWentWrong())
      return(INIT_FAILED);
   b = new B;
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   delete a;
   delete b;
  }

void OnTick() {}

bool somethingWentWrong() { return(true); }

Is this code correct? Deleting a non-existent object does not cause runtime errors. Or is it better to do it like this:

void OnDeinit(const int reason)
  {
   if(CheckPointer(a) == POINTER_DYNAMIC)
      delete a;
   if(CheckPointer(b) == POINTER_DYNAMIC)
      delete b;
  }
 
Vladislav Boyko #:

Can I expect the default constructors of member objects to be called before the constructor body starts executing?

The following test shows that it works:

But can I expect this to work always (I didn't find anything in the documentation about this)?

Or is it better to explicitly call the default constructors for member objects in the initialization list?

That is, is what I highlighted redundant?


It is not redundant, but explicit versus implicit.

Also, yes, initialization list always comes first.


Reason: