MQL5 El compilador no distingue entre una clase y un puntero a ella - página 12

 
Georgiy Merts:

No. Está claro que en este caso la variable debe borrarse al salir del bloque.

Me refiero a los objetos creados por new:

El estándar C# especifica: "Tanto los objetos de tipo valor, como las estructuras, como los objetos de tipo referencia, como las clases, se destruyen automáticamente, pero los objetos de tipo valor se destruyen cuando se destruye el contexto que los contiene, mientras que los objetos de tipo referencia son destruidos por el recolector de basura indefinidamente después de que se elimine la última referencia a ellos."

Aquí, no me gusta este "tiempo imprevisible". Aunque, incluso admito que el recolector de basura puede eliminar el objeto mucho más eficazmente, que yo mismo eliminar el objeto en el destructor de la clase que lo creó.

Lógicamente, como nadie lo está referenciando significa que ya nadie necesita el objeto, se borrará en la próxima recogida de basura. El tiempo es imprevisible, aunque puedes pedir a la GC que lo construya inmediatamente. Pero esto también es una petición, no una orden ))).

 
Georgiy Merts:

No estoy diciendo que el recolector de basura borre un objeto vivo o un puntero. Digo que lo quitará cuando quiera.

Sharp tiene una función para proteger el objeto de ser borrado por el recolector de basura.

https://docs.microsoft.com/ru-ru/dotnet/api/system.runtime.interopservices.gchandle.alloc?view=netcore-2.0

// for standalone object
public byte[] RawSerialize(object objAny)
{
int rawsize = Marshal.SizeOf(objAny);
byte[] m_obj = new byte[rawsize];

        GCHandle hObj = GCHandle.Alloc(m_obj, GCHandleType.Pinned);

        Marshal.StructureToPtr(objAny, hObj.AddrOfPinnedObject(), false);
        hObj.Free();

return (m_obj);
}
GCHandle.Alloc Method (System.Runtime.InteropServices)
GCHandle.Alloc Method (System.Runtime.InteropServices)
  • dotnet-bot
  • docs.microsoft.com
Выделяет дескриптор для указанного объекта.Allocates a handle for the specified object.
 
Alexey Navoykov:

Y ahora intentas desesperadamente inventar excusas de por qué no lo sabías ;)

¿Qué más da que lo hayan presentado inmediatamente o meses después? No te habrías enterado y seguirías sin enterarte si no te lo hubiera dicho).

Temo arder de vergüenza, pero no conocía & & hasta hace poco, hasta que lo vi en algún sitio de fxsaber. De lo contrario, utilizaría GetPointer.

Pero he prestado atención a la ausencia de la posibilidad de sobrecargar algunas operaciones con objetos en septiembre en algún lugar y en ese momento he tratado de resolver este problema por mí mismo y algunas personas me escribieron que tal posibilidad no existe. Y ahora resulta que existe, por lo que me pregunto cuándo apareció exactamente (y por qué no está en la ayuda).

 
SemenTalonov:

Probablemente, irán en la dirección de C# donde el "código gestionado" no tiene punteros y todo tiene un objeto, incluso los tipos simples bool int double, etc.

Esto estaría bien, pero es poco probable que cambien algo en este sentido, porque es un cambio completo en el concepto del lenguaje de los terminales, y esas cosas rara vez se hacen.

SemenTalonov:

Exactamente según IMHO es necesario no olvidar de qué se trata exactamente (objeto o puntero a él).

Para no olvidarlo, hay que decidir con seguridad al principio cuándo se usan objetos y cuándo punteros (lo ideal es no usar nunca objetos y siempre punteros).

Y es una tontería escribir cada vez letras adicionales para ello (sobre todo molestarse en poner paréntesis).

Además, en este caso, la operación de asignación descrita por usted se utiliza no en relación con un objeto sino con su campo no objetual lo que, en principio, excluye una probabilidad de error (el tipo de puntero en dicha operación no importa).

 
Ilya Malev:

Para no olvidarse, hay que decidir exactamente al principio cuándo se utilizan objetos y cuándo punteros (lo ideal es no utilizar nunca objetos y siempre punteros).

Cuando abres tu propio código después de mucho tiempo (un año o dos) y te regañas por no haber dejado comentarios en los lugares "delicados", o por no saber distinguir los objetos de los punteros, es como una pérdida total. Tampoco estoy de acuerdo en que debamos rechazar el uso de autoobjetos. Su uso hace que el código sea compacto y reduce la preocupación por el destino del objeto una vez que se ha quedado obsoleto. Además, estoy seguro de que el compilador conoce de antemano el tiempo de vida de dicho objeto y, por tanto, puede proporcionar un código más optimizado que en el caso de la creación dinámica.

Ilya Malev:

Y es una tontería escribir letras adicionales cada vez para eso (sobre todo molestarse con los paréntesis).

Además, en el caso que describes, la operación de asignación no se utiliza en relación con un objeto, sino con su campo no objetual, lo que básicamente excluye una probabilidad de error (el tipo de puntero en tal operación no importa).

Esta tontería viene del hecho de que en MQL no hay otra forma de denotar el acceso a un objeto mediante un puntero. En C/C++, por supuesto, sería más lacónico.

pA->iValue

La razón de la ausencia de la flecha es probablemente la misma que la del"*" originalmente (desconocida). En Qt (y probablemente también en VS), el editor sustituye automáticamente '.' por '->' si se accede al objeto a través de un puntero, es decir, sin ningún trabajo extra. No me cabe duda de que MQ puede añadir esa funcionalidad al editor, si así lo desea. Resulta que en este ejemplo la única señal de que se trata de un puntero es el prefijo 'p' en el nombre. Y eso es sólo porque no lo he olvidado. Si todo el mundo tiene tanto "tacto" entonces está bien))

Es decir, los fragmentos de código potencialmente peligrosos deben marcarse explícitamente. No hay que recordarlos, hay que verlos. La necesidad de esta "formalización de las relaciones" con los objetos sería más clara en muestras más complicadas que las dadas anteriormente. Por ejemplo, cuando un miembro de la clase es en sí mismo un puntero a algo.

Al proporcionar una manera uniforme de tratar conPOINTER_AUTOMATIC yPOINTER_DYNAMIC, se nos da la idea errónea de que estos tipos de punteros son similares. Pero, de hecho, son entidades diferentes y requieren un tratamiento distinto. Este es el tema principal de esta rama.El más obvio es, por supuesto: mientras quePOINTER_AUTOMATICsiempre apunta a un objeto real,POINTER_DYNAMIC también puede estar vacío.

Y sólo voy a recordar todas las diferentes variaciones de acceso a los datos (aunque C/C++, siempre que nuestras rutas coincidan)

OperadorSintaxisRecargableImplementado enCEjemplo
Miembro del tipo TDefinición fuera de la clase
Acceso a un elemento de la matriza[b]RT::operador[](Sb);
n/a
Referencia indirecta ("objeto señaladopor a")*aRT::operador*();Operador R*(Ta);
Referencia ("direccióna")& aR operadorT::operador&();Operador R&(Ta);
Referencia a un miembro de la estructura ("el miembro b del objeto apuntado pora")a-> bR*T::operator->();[nota 5]
N/A
Referencia a un miembro de una estructura ("miembro b del objetoa")a. bNon/a
Miembro señalado por b en un objeto señalado pora[nota 6]a->*bNoR operadorT::operador->*(Sb);Operador R->*(Ta, Sb);
El miembro apuntado por b en el objetoaa.*bNoNoN/A
 
SemenTalonov:

Bueno, la más obvia, por supuesto: siPOINTER_AUTOMATIC siempre apunta a un objeto real, entoncesPOINTER_DYNAMIC también puede estar vacío.

Si lo "más obvio" ya es falso, ¿merece la pena considerar seriamente y responder a todo lo demás?

POINTER_AUTOMATIC no es el tipo de variable, es su estado. Al momento siguiente su estado puede ser muy diferente. Incluyendo POINTER_INVALID, por supuesto.
 
Ilya Malev:

Si lo "más obvio" ya es falso, ¿merece la pena considerar seriamente y responder a todo lo demás?

Me gustaría que me aclararan esto si es posible

 
Ilya Malev:
POINTER_AUTOMATIC no es un tipo de variable sino su estado. En el siguiente momento, su estado puede ser muy diferente

Ciertamente no es un tipo. ¿Quieres decir que el auto-objeto se convierte en un puntero con el estadoPOINTER_DYNAMIC, por ejemplo? Se trata delestadoPOINTER_INVALID al declarar un puntero, por ejemplo.

 
SemenTalonov:

Me gustaría que me aclararan esto, si es posible.

Es que en MCL aparentemente no es lo mismo que en C++. Aquí un puntero no es un tipo de datos separado en absoluto, por lo que ambos son objetos y una variable contiene su manejador. Una variable tiene una propiedad constante oculta (si se declara sin *), pero eso no la convierte esencialmente en una variable de un tipo diferente, sólo prohíbe asignarle un manejador diferente.

 

Es decir, declarar

   A* const b=new A;

Y tendrás exactamente el mismo "auto-objeto", sólo que lo borrarás tú mismo