Errors, bugs, questions - page 2198

 
fxsaber:

No difference


When typing, it appears to depend on the numbers you type. Some of them don't allow you to type. And some of them do.

Strange behaviour... If you type a whole number less than 12 digits, it may skip a total of more than 14.

We will wait to see what the developers say.

 
Please help me to do a simple thing
class A
{
public:  
  int i;
  
  A* operator *( const A &Value ) const
  {
    A* Res = new A;
    
    Res.i = this.i * Value.i;
    
    return(Res);
  }
};

void OnStart()
{
  A a, b, c;
  
  a.i = 2;
  b.i = 3;
  c.i = 5;
  
  A* d = a * b * c;
  
  Print(d.i); // 30
  
  delete d;
}

You can clearly see in the code that there should be a memory leak. And that is exactly what is happening. However, how to write it correctly to be able to "multiply" objects? Everything is clear with "*=" operator, as it is clear in case of structures. But with classes, how to implement this simple functionality?


SZZ And this code.

class A
{
private:
  A Tmp;
  
public:
  int i;
  
  A* operator *( const A &Value )
  {
    this.Tmp.i = this.i * Value.i;
    
    return(&Tmp);
  }
};

void OnStart()
{
  A a, b, c;
  
  a.i = 2;
  b.i = 3;
  c.i = 5;
  
  A* d = a * b * c;
  
  Print(d.i); // 30
}

Crashes ME by F7 and kills Terminal by F5. Why am I so lucky!

 
fxsaber:

ZS And this code

Crashes ME on F7 and kills Terminal on F5. Why am I so lucky?!

class A
{
private:
  A Tmp;
  
public:
  int i;
  
  A* operator *( const A &Value )
  {
    this.Tmp.i = this.i * Value.i;
    
    return(&Tmp);
  }
};

void OnStart()
{
  A a, b, c;
  
  a.i = 2;
  b.i = 3;
  c.i = 5;
  
  A* d = a * b * c;
  
  Print(d.i); // 30
}

Probably infinite recursion and stack overflow.

 
Sergey Dzyublik:

Possibly infinite recursion and stack overflow.

Certainly the problem is in the allocated one, but the cause seems to be deeper.

And there should obviously be no recursion at runtime.

 
fxsaber:
Please help me to do a simple thing
class A
{
public:
  A() {}
  A(const A& other) 
  {
   this.i = other.i;
  }
  
  int i;
  
  A operator *( const A &Value ) const
  {
    A Res;
    
    Res.i = this.i * Value.i;
    
    return(Res);
  }
};

void OnStart()
{
  A a, b, c;
  
  a.i = 2;
  b.i = 3;
  c.i = 5;
  
  A d = a * b * c;
  
  Print(d.i); // 30
}
Overhead of course, but if convenience is more important...
 
Комбинатор:
Overhead of course will be, but if convenience is more important...

Thank you! It turns out that return object and "=" when defining an object go through additional constructor.

I'd actually like to see a clear table somewhere, which cases are called constructors (and which ones), and which ones are called operators. Right now everything is intuitive, which fails, of course.

 
fxsaber:

I would actually like to see a table somewhere, where constructors are called (and which ones) and where operators are called. Right now it's all at the level of intuition, and it fails, of course.

If you return something by value, it will be assigned via copy-constructor (if the same type) if it's a definition or operator if not.

void OnStart()
{
  A a, b, c;
  
  a.i = 2;
  b.i = 3;
  c.i = 5;
  
  A d = a * b * c;
  // код аналогичен A d(a * b * c);
  // будет вызван копи-конструктор.

  A e;
  e = a * b * c;
  // будет вызван оператор =
  // но копи-конструктор все равно нужен для множественного умножения
  
  Print(d.i); // 30
}
 
Комбинатор:

If you return something by value, it will be assigned via copy-constructor (if the same type) if it is a definition or operator if not.

Clearly stated, thank you!


SZZ primed your code

class A
{
public:
  A() { Print(__FUNCSIG__); }
  A(const A& other) 
  {
   Print(__FUNCSIG__);
   this.i = other.i;
  }
  
  ~A()
  {
   Print(__FUNCSIG__);
  }
  
  int i;
  
  A operator *( const A &Value ) const
  {
    Print(__FUNCSIG__);

    A Tmp;
    
    Tmp.i = this.i * Value.i;
        
    return(Tmp);
  }
};

void OnStart()
{
  if (true)
  {
    A a, b, c;
    
    a.i = 2;
    b.i = 3;
    c.i = 5;
    
    A d = a * b * c;

    Print(d.i); // 30
  }
  
  Print("Kill!");  
}


Result

void A::A() // a
void A::A() // b
void A::A() // c
A A::operator*(const A&) const
void A::A() // Tmp
void A::A(const A&) // return
void A::~A() // Tmp
A A::operator*(const A&) const
void A::A() // Tmp
void A::A(const A&) // return
void A::~A() // Tmp
void A::A(const A&) // d
30
void A::~A() // a
void A::~A() // b
void A::~A() // c
void A::~A() // d
void A::~A() // return
void A::~A() // return
Kill!

The highlighted lines raise questions. Why didn't the temporary objects crash as soon as they were used? That is, before the output of thirty. Such objects would crash my machine since it's supposed to handle tens of millions of ticks. Each object will gobble up gigabytes of RAM, and I don't want to have such temporary objects instead of immediately killing them.

 
fxsaber:

The highlighted lines raise questions. Why didn't the temporary objects crash as soon as they were used? I.e. before the output of thirty.

Usually temporary objects are not deleted immediately, but at the end of the context.

If you want fast deletion, control the context.

void OnStart()
{
  if (true)
  {
    A a, b, c;
    
    a.i = 2;
    b.i = 3;
    c.i = 5;
    
    A d;
    {
      d = a * b * c;
    }

    Print(d.i); // 30
  }
  
  Print("Kill!");  
}

True, you will have to use operator =

 
A100:

On my new graph, the example only worked when I restarted it (all the buttons), which in itself is incomprehensible. But now I understand this

With the opening of trades, the specified effect is gone (only on restart)

Made edits to the documentation. The problem with the code was that sending a mouse event order to the chart is only putting the command into the chart's queue. And if this queue is not processed (for example at weekend), the chart cannot receive the specified events. Added note and corrected example to ChartSetInteger description:

Note

The function is asynchronous - it means that the function does not wait for the execution of the command, successfully queued for the specified chart, but returns control immediately. The property will only change after the command has been processed in the graph queue. The ChartRedraw function must be called to immediately execute commands in the chart queue.

If you need to immediately change several chart properties, the appropriate functions (ChartSetString, ChartSetDouble, ChartSetString) must be executed in one code block and then ChartRedraw must be called once.

To check the result of the execution, you can use a function that queries the specified chart property (ChartGetInteger, ChartGetDouble, ChartSetString). Note that these functions are synchronous and wait for the result of execution.

Example:

//+------------------------------------------------------------------+
//| Expert initialization function|
//+------------------------------------------------------------------+
voidOnInit()
{
//--- enable messages about the mouse movement through the chart window
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1);
//--- forced update of chart properties ensures readiness for event handling
ChartRedraw()
;
}


Reason: