Erros, bugs, perguntas - página 1951

 
Stanislav Korotky:

Existe alguma forma de devolver uma instância de objecto anónima de uma função?

Substitui-la por uma macro.
 
fxsaber:
Substitui-la por uma macro.

Não vai funcionar. Este é um método de classe e o param é de facto retirado do objecto. Simplifiquei-o aqui, por exemplo.

 
Stanislav Korotky:

Não vai funcionar. Este é um método de classe e o param é de facto retirado do objecto. Simplifiquei-o aqui, por exemplo.

É claro que é melhor familiarizar-se com a tarefa original.

Seria errado devolver um ponteiro?

 

Stanislav Korotky:

Funciona, excepto que cria uma cópia interna extra, ea declaração de retorno requer um construtor de cópias na classe. Embora a cópia seja pregada quando a função sai, eu gostaria de eliminar a cópia em si.


Class function()
{
  int param = 0;
  Class obj(param);
  return obj;
}

Claro que sim, a variável local é destruída quando a função sai.
Usar novo e devolver o ponteiro, qual é o problema?

Se precisar de controlo de recursos, utilize um invólucro como um ponteiro inteligente.
Talvez pudesse usar algo dos Padrões de Criação como singleton ou construtor...

 
fxsaber:

É claro que é melhor familiarizar-se com a tarefa original...

Seria errado devolver o ponteiro?

Isso estava originalmente em indicações. Mas então o código do cliente seria responsável pela sua remoção, e isso é um monte de lixo, para não mencionar o facto de ser preciso um piscar de olhos e ficar com as ligações suspensas.

 
Sergey Dzyublik:

Claro que sim, depois de sair da função, a variável local é destruída.

Usar novo e devolver um ponteiro, qual é o problema?

Se precisar de controlo de recursos, utilize um invólucro como um ponteiro inteligente.
Talvez algo dos Padrões Criativos como singleton ou construtor funcione para si.

Os apontadores estão lá - inconvenientes (respondido acima). Tentei olhar para os "espertos". Mas a minha impressão é que para a MQL um ponteiro inteligente só dará outro nível de referencialidade, que terá de ser monitorizado por sua vez. Afinal de contas, o que é um ponteiro inteligente? - É um objecto de invólucro no qual é colocada a referência inicial. E quem e quando irá limpar o invólucro? ;-) Se tiver soluções prontas, por favor, largue-me uma linha. Tenho um caso de teste por agora.

 
Stanislav Korotky:

Afinal de contas, o que é um ponteiro inteligente? - É um objecto de invólucro no qual é colocada a referência original. E quem e quando irá limpar o invólucro? ;-) Se tiver soluções prontas, por favor, largue-me uma linha. Tenho um caso de teste por agora.


Utilizar o shared_ptr.
Não precisa de limpar este invólucro, basta copiá-lo e partilhar_ptr é quantas instâncias de recurso desejado são deixadas e quando libertar este ou aquele recurso.


Não há soluções prontas, pelo menos para mim. Adaptar os C++.

 
Sergey Dzyublik:

Não há soluções prontas, pelo menos não para mim. Adaptar os de C++.

É compreensível - é isso que estou a fazer, mas já existe a impressão de que a MQL não lhe permitirá fazer um "rastreio".

 
Stanislav Korotky:

Existe alguma forma de devolver uma instância de objecto anónima de uma função?

Como alguém já assinalou aqui, a forma mais correcta é devolver um ponteiro inteligente de uma função. Tudo isto é implementado em MQL. Embora não seja tão conveniente de utilizar como em C++, porque a passagem pelo ponteiro deve ser implementada através do método, e não através do operador de passagem. A propósito, para a tarefa em mãos suponho que o shared_ptr não é necessário, o unique_ptr será suficiente.

Em alternativa, o ponteiro criado dentro da função poderia ser imediatamente colocado em alguma matriz global, que seria destruída no final do programa. Ao mesmo tempo, o utilizador pode libertar a memória do objecto a qualquer momento, chamando uma função especial (não eliminar). É como CloseHandle em WinApi.

Funciona, excepto que uma cópia interna extra é criada e o operador de retorno requer um construtor de cópias na classe. Embora a cópia seja pregada quando a função sai, gostaria de eliminar a própria cópia.

Talvez o compilador seja inteligente o suficiente para optimizar e alinhar tudo por si só, excluindo a cópia desnecessária. Mas temos de o verificar. Seria bom se alguém realizasse testes e medições. Porque também me vejo frequentemente confrontado com um tal dilema.

 
Alexey Navoykov:

Como alguém já assinalou, a forma correcta de o fazer é devolver um ponteiro inteligente de uma função. Tudo isto é implementado em MQL. Mas não é tão conveniente de usar como em C++, porque o interruptor ponteiro deve ser implementado através do método, não através do operador do interruptor. A propósito, para a tarefa em mãos suponho que o shared_ptr não é necessário, o unique_ptr será suficiente.

Em alternativa, o ponteiro criado dentro da função poderia ser imediatamente colocado em alguma matriz global, que seria destruída no final do programa. Ao mesmo tempo, o utilizador pode libertar a memória do objecto a qualquer momento, chamando uma função especial (não eliminar). É como CloseHandle em WinApi.

Talvez o compilador seja suficientemente esperto para optimizar tudo e alinhá-lo por si só, eliminando a cópia desnecessária. Mas temos de o verificar. Seria bom se alguém realizasse testes e medições. Caso contrário, também me vejo frequentemente confrontado com um tal dilema.

Estou a publicar a minha implementação abaixo - de qualquer modo, estes pontos inteligentes são criados temporariamente, e como resultado estou apenas a criar e a pregar mais objectos do que tinha ;-).

É claro que tenho em mente a variante da matriz global, mas é tão feia! Especialmente porque eu queria limpar por temporizador (porque o programa pode funcionar durante dias), e o temporizador em MQL não pode ser ligado a uma classe/objecto - vem apenas do manipulador global.

O compilador não ajuda aqui - testado - o objecto local por devolução é duplicado e depois pregado. Neste caso, não há uma jogada ideal.

template<typename T>
class auto_ptr
{
  private:

    class Reference
    {
      public:
        int count;
        Reference(): count(0) {}
    };

    T *data;
    Reference *reference;

    void remove()
    {
      if(reference != NULL)
      {
        reference.count--;
        if(reference.count == 0)
        {
          delete data;
          delete reference;
        }
      }
    }

    
  public:
    auto_ptr(): data(NULL), reference(NULL)
    {
    }
    auto_ptr(T *ptr): data(ptr), reference(ptr == NULL ? NULL : new Reference())
    {
      if(reference != NULL) reference.count++;
    }
    auto_ptr(auto_ptr<T> &ref): data(ref.data), reference(ref.reference)
    {
      reference.count++;
    }
    
    ~auto_ptr()
    {
      remove();
    }
    
    void operator=(auto_ptr<T> &next)
    {
      if(&this != &next)
      {
        remove();
        
        data = next.data;
        reference = next.reference;
        reference.count++;
      }
    }
};