Errores, fallos, preguntas - página 1951

 
Stanislav Korotky:

¿Hay alguna forma de devolver una instancia de objeto anónimo desde una función?

Sustitúyalo por una macro.
 
fxsaber:
Sustitúyalo por una macro.

No funcionará. Este es un método de clase y el parámetro se toma realmente del objeto. Lo he simplificado aquí, por ejemplo.

 
Stanislav Korotky:

No funcionará. Este es un método de clase y el parámetro se toma realmente del objeto. Lo he simplificado aquí, por ejemplo.

Será mejor que te familiarices con la tarea original, por supuesto...

¿Estaría mal devolver un puntero?

 

Stanislav Korotky:

Funciona, excepto que crea una copia interna extra, yla declaración de retorno requiere un constructor de copia en la clase. Aunque la copia se clava cuando la función sale, me gustaría eliminar la copia en sí.


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

Por supuesto que sí, la variable local se destruye cuando la función sale.
Usar new y devolver el puntero, ¿cuál es el problema?

Si necesita controlar los recursos, utilice un envoltorio como el puntero inteligente.
Tal vez podrías usar algo de Creational Patterns como singleton o builder...

 
fxsaber:

Mejor, por supuesto, familiarizarse con la tarea original...

¿Estaría mal devolver el puntero?

Eso fue originalmente en punteros. Pero luego el código del cliente se encarga de eliminarlos, y eso es mucha basura, por no hablar de que tarda un parpadeo y te quedas con los enlaces suspendidos.

 
Sergey Dzyublik:

Por supuesto que sí, después de salir de la función la variable local se destruye.

Usar new y devolver un puntero, ¿cuál es el problema?

Si necesita controlar los recursos, utilice un envoltorio como el puntero inteligente.
Tal vez algo de Creational Patterns como singleton o builder te sirva.

Los punteros están ahí - inconveniente (contestado arriba). He intentado mirar hacia la "inteligencia". Pero mi impresión es que para MQL un puntero inteligente sólo dará otro nivel de referencialidad, que tendrá que ser controlado a su vez. Después de todo, ¿qué es un puntero inteligente? - Es un objeto envolvente en el que se coloca la referencia inicial. ¿Y quién y cuándo limpiará el envoltorio? ;-) Si tienes soluciones preparadas, por favor, escríbeme. Por ahora tengo un caso de prueba.

 
Stanislav Korotky:

Después de todo, ¿qué es un puntero inteligente? - Es un objeto envolvente en el que se coloca la referencia original. ¿Y quién y cuándo limpiará el envoltorio? ;-) Si tienes soluciones preparadas, por favor, escríbeme. Por ahora tengo un caso de prueba.


Utiliza shared_ptr.
No es necesario limpiar esta envoltura, sólo la copias y shared_ptr es cuántas instancias del recurso deseado quedan y cuándo liberar tal o cual recurso.


No hay soluciones prefabricadas, al menos para mí. Adaptar los de C++.

 
Sergey Dzyublik:

No hay soluciones prefabricadas, al menos no para mí. Adapta los de C++.

Es comprensible - es lo que estoy haciendo, pero ya tengo la impresión de que MQL no permite hacer "tracing".

 
Stanislav Korotky:

¿Hay alguna forma de devolver una instancia de objeto anónimo desde una función?

Como alguien ya ha señalado aquí, lo más correcto es devolver un puntero inteligente desde una función. Todo esto se implementa en MQL. Aunque no es tan cómodo de usar como en C++, porque el paso por puntero debe implementarse a través de un método, en lugar de a través del operador pass. Por cierto, para la tarea que nos ocupa supongo que shared_ptr no es necesario, con unique_ptr será suficiente.

Alternativamente, el puntero creado dentro de la función podría ser colocado inmediatamente en algún array global, que sería desechado al final del programa. Al mismo tiempo, el usuario puede liberar la memoria del objeto en cualquier momento llamando a una función especial (no borrar). Es como CloseHandle en WinApi.

Funciona, excepto que se crea una copia interna extra y el operador de retorno requiere un constructor de copia en la clase. Aunque la copia se clava cuando la función sale, me gustaría eliminar la copia en sí.

Tal vez el compilador sea lo suficientemente inteligente como para optimizar y alinear todo por sí mismo, excluyendo las copias innecesarias. Pero tenemos que comprobarlo. Estaría bien que alguien realizara pruebas y mediciones. Porque yo también me encuentro a menudo con ese dilema.

 
Alexey Navoykov:

Como alguien ya ha señalado, la forma correcta de hacerlo es devolver un puntero inteligente desde una función. Todo esto se implementa en MQL. Pero no es tan cómodo de usar como en C++, porque el cambio de puntero debe implementarse a través de un método, no a través de un operador de cambio. Por cierto, para la tarea que nos ocupa supongo que shared_ptr no es necesario, con unique_ptr será suficiente.

Alternativamente, el puntero creado dentro de la función podría ser colocado inmediatamente en algún array global, que sería desechado al final del programa. Al mismo tiempo, el usuario puede liberar la memoria del objeto en cualquier momento llamando a una función especial (no borrar). Es como CloseHandle en WinApi.

Tal vez el compilador sea lo suficientemente inteligente como para optimizar todo y ponerlo en línea por sí mismo, eliminando las copias innecesarias. Pero tenemos que comprobarlo. Estaría bien que alguien realizara pruebas y mediciones. Por lo demás, yo también me encuentro a menudo con ese dilema.

Voy a publicar mi implementación más abajo - de todas formas estos smart-pointers se crean temporalmente, y como resultado sólo estoy creando y clavando más objetos de los que tenía ;-).

Por supuesto, tengo en mente la variante de array global, ¡pero es tan feo! Especialmente porque quería limpiar por temporizador (porque el programa puede funcionar durante días), y el temporizador en MQL no se puede adjuntar a una clase/objeto - sólo viene del manejador global.

El compilador no ayuda aquí - probado - el objeto local por el retorno es duplicado y luego clavado. No hay un movimiento óptimo en este caso.

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++;
      }
    }
};