Errores, fallos, preguntas - página 2198

 
fxsaber:

No hay diferencia


Al escribir, parece que depende de los números que se escriban. Algunos de ellos no te permiten escribir. Y algunos lo hacen.

Un comportamiento extraño... Si escribe un número entero de menos de 12 dígitos, puede saltar un total de más de 14.

Esperaremos a ver qué dicen los desarrolladores.

 
Por favor, ayúdenme a hacer una cosa sencilla
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;
}

Puedes ver claramente en el código que debería haber una fuga de memoria. Y eso es exactamente lo que está ocurriendo. Sin embargo, ¿cómo escribirlo correctamente para poder "multiplicar" los objetos? Todo está claro con el operador "*=", como lo está en el caso de las estructuras. Pero con las clases, ¿cómo implementar esta sencilla funcionalidad?


SZZ Y este código.

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
}

Cierra ME con F7 y mata el Terminal con F5. ¿Por qué tengo tanta suerte?

 
fxsaber:

ZS Y este código

Se bloquea ME en F7 y mata el Terminal en F5. ¿Por qué tengo tanta suerte?

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
}

Probablemente recursión infinita y desbordamiento de pila.

 
Sergey Dzyublik:

Posible recursión infinita y desbordamiento de pila.

Ciertamente el problema está en el asignado, pero la causa parece ser más profunda.

Y obviamente no debería haber recursión en tiempo de ejecución.

 
fxsaber:
Por favor, ayúdenme a hacer una cosa sencilla
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
}
Los gastos generales, por supuesto, pero si la comodidad es más importante...
 
Комбинатор:
Por supuesto que habrá gastos generales, pero si la comodidad es más importante...

Gracias. Resulta que el objeto de retorno y "=" al definir un objeto pasan por un constructor adicional.

De hecho, me gustaría ver una tabla clara en algún lugar, qué casos se llaman constructores (y cuáles), y cuáles se llaman operadores. Ahora mismo todo es intuitivo, lo que falla, claro.

 
fxsaber:

En realidad, me gustaría ver una tabla en algún lugar, donde se llaman los constructores (y cuáles) y donde se llaman los operadores. Ahora mismo todo está a nivel de intuición, y falla, claro.

Si devuelve algo por valor, se asignará a través del constructor-copia (si es del mismo tipo) si es una definición o del operador si no.

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
}
 
Комбинатор:

Si devuelve algo por valor, se asignará a través del constructor-copia (si es del mismo tipo) si es una definición o del operador si no.

Claramente expuesto, ¡gracias!


SZZ ha preparado su código

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!");  
}


Resultado

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!

Las líneas resaltadas plantean preguntas. ¿Por qué los objetos temporales no se bloquean en cuanto se utilizan? Es decir, antes de la salida de treinta. Tales objetos colapsarían mi máquina ya que se supone que debe manejar decenas de millones de ticks. Cada objeto engullirá gigabytes de RAM, y no quiero tener esos objetos temporales en lugar de matarlos inmediatamente.

 
fxsaber:

Las líneas resaltadas plantean preguntas. ¿Por qué los objetos temporales no se bloquean en cuanto se utilizan? Es decir, antes de la salida de treinta.

Normalmente los objetos temporales no se eliminan inmediatamente, sino al final del contexto.

Si quieres un borrado rápido, controla el contexto.

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!");  
}

Verdadero, tendrá que utilizar el operador =

 
A100:

En mi nueva gráfica, el ejemplo sólo ha funcionado cuando la he reiniciado (todos los botones), lo que de por sí es incomprensible. Pero ahora entiendo esto

Con la apertura de operaciones, el efecto especificado desaparece (sólo al reiniciar)

Se ha editado la documentación. El problema con el código era que al enviar una orden de evento de ratón al gráfico sólo se pone la orden en la cola del gráfico. Y si esta cola no se procesa (por ejemplo en fin de semana), el gráfico no puede recibir los eventos especificados. Se ha añadido una nota y un ejemplo corregido a la descripción de ChartSetInteger:

Nota

La función es asíncrona - significa que la función no espera la ejecución del comando, puesto en cola con éxito para el gráfico especificado, sino que devuelve el control inmediatamente. La propiedad sólo cambiará después de que el comando haya sido procesado en la cola de gráficos. La función ChartRedraw debe ser llamada para ejecutar inmediatamente los comandos en la cola del gráfico.

Si necesita cambiar inmediatamente varias propiedades del gráfico, las funciones apropiadas (ChartSetString, ChartSetDouble, ChartSetString) deben ser ejecutadas en un bloque de código y luego ChartRedraw debe ser llamado una vez.

Para comprobar el resultado de la ejecución, puede utilizar una función que consulte la propiedad del gráfico especificada (ChartGetInteger, ChartGetDouble, ChartSetString). Tenga en cuenta que estas funciones son sincrónicas y esperan el resultado de la ejecución.

Ejemplo:

//+------------------------------------------------------------------+
//| Función de inicialización de expertos|
//+------------------------------------------------------------------+
voidOnInit()
{
//--- habilitar los mensajes sobre el movimiento del ratón a través de la ventana del gráfico
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1);
//--- la actualización forzada de las propiedades del gráfico asegura la preparación para el manejo de eventos
ChartRedraw()
;
}


Razón de la queja: