Erros, bugs, perguntas - página 2198

 
fxsaber:

Sem diferença


Quando se digita, parece depender dos números que se digita. Alguns deles não lhe permitem escrever à máquina. E alguns deles têm.

Estranho comportamento... Se escrever um número inteiro inferior a 12 dígitos, pode saltar um total de mais de 14.

Vamos esperar para ver o que os criadores dizem.

 
Por favor, ajude-me a fazer uma coisa simples
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;
}

O código mostra claramente que deve haver uma fuga de memória. E é exactamente isso que está a acontecer. No entanto, como escrevê-lo correctamente para poder "multiplicar" os objectos? Tudo é claro com o operador "*=", como é claro no caso de estruturas. Mas com as aulas, como implementar esta simples funcionalidade?


SZZ E 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
}

Destrói ME por F7 e mata Terminal por F5. Porque tenho tanta sorte!

 
fxsaber:

ZS E este código

Destrói ME em F7 e mata Terminal em F5. Porque é que tenho tanta sorte?!

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
}

Provavelmente recorrência infinita e transbordamento da pilha.

 
Sergey Dzyublik:

Possivelmente recorrência infinita e transbordamento da pilha.

Certamente o problema está no atribuído, mas a causa parece ser mais profunda.

E não deve obviamente haver repetição em tempo de execução.

 
fxsaber:
Por favor, ajude-me a fazer uma coisa simples
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
}
Acima de tudo, claro, mas se a conveniência é mais importante...
 
Комбинатор:
Acima de tudo, claro, mas se a conveniência for mais importante...

Obrigado! Acontece que o objecto de retorno e "=" ao definir um objecto passam por um construtor adicional.

Na verdade, gostaria de ver uma tabela clara algures, quais são os casos chamados construtores (e quais), e quais são os chamados operadores. Neste momento tudo é intuitivo, o que falha, é claro.

 
fxsaber:

Na verdade, gostaria de ver uma tabela algures, onde os construtores são chamados (e quais) e onde os operadores são chamados. Neste momento está tudo ao nível da intuição, e falha, é claro.

Se devolver algo por valor, será atribuído através de copy-constructor (se for do mesmo tipo) se for uma definição ou operador se não for.

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

Se devolver algo por valor, será atribuído através de copy-constructor (se for do mesmo tipo) se for uma definição ou operador se não for.

Claramente declarado, obrigado!


A SZZ preparou o seu 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!

As linhas destacadas levantam questões. Porque é que os objectos temporários não se despenharam assim que foram utilizados? Ou seja, antes de se produzirem trinta. Tais objectos iriam bater com a minha máquina, uma vez que é suposto lidar com dezenas de milhões de carraças. Cada objecto devorará gigabytes de RAM, e eu não quero ter tais objectos temporários em vez de os matar imediatamente.

 
fxsaber:

As linhas destacadas levantam questões. Porque é que os objectos temporários não se despenharam assim que foram utilizados? Isto é, antes da produção de trinta.

Normalmente, os objectos temporários não são eliminados imediatamente, mas no fim do contexto.

Se quiser uma eliminação rápida, controle o 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!");  
}

É verdade, terá de utilizar operador =

 
A100:

No meu novo gráfico, o exemplo só funcionou quando o reiniciei (todos os botões), o que em si mesmo é incompreensível. Mas agora compreendo isto

Com a abertura das negociações, o efeito especificado desaparece (apenas no reinício)

Fez edições à documentação. O problema com o código era que enviar uma ordem de evento do rato para o gráfico é apenas colocar o comando na fila do gráfico. E se esta fila não for processada (por exemplo, ao fim-de-semana), o gráfico não pode receber os eventos especificados. Adicionada nota e exemplo corrigido à descrição do ChartSetInteger:

Nota

A função é assíncrona - isto significa que a função não espera pela execução do comando, enfileirada com sucesso para o gráfico especificado, mas devolve o controlo imediatamente. A propriedade só mudará depois de o comando ter sido processado na fila gráfica. A função ChartRedraw deve ser chamada para executar imediatamente os comandos na fila do gráfico.

Se precisar de alterar imediatamente várias propriedades do gráfico, as funções apropriadas (ChartSetString, ChartSetDouble, ChartSetString) devem ser executadas num bloco de código e depois o ChartRedraw deve ser chamado uma vez.

Para verificar o resultado da execução, pode usar uma função que consulta a propriedade especificada do gráfico (ChartGetInteger, ChartGetDouble, ChartSetString). Note-se que estas funções são síncronas e aguardam o resultado da execução.

Exemplo:

//+------------------------------------------------------------------+
//| Função de iniciação de peritos|
//+------------------------------------------------------------------+
nuloOnInit()
{
//--- activar mensagens sobre o movimento do rato através da janela do gráfico
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1);
//--- actualização forçada das propriedades do gráfico garante a prontidão para o tratamento de eventos
ChartRedraw()
;
}


Razão: