MQL5 O compilador não faz distinção entre uma classe e um ponteiro para ela - página 12

 
Georgiy Merts:

Não. Claramente, neste caso, a variável deve ser apagada na saída do bloco.

Estou falando de objetos criados por novos:

A norma C# especifica:"Tanto objetos do tipo valor, como estruturas, quanto objetos do tipo referência, como classes, são destruídos automaticamente, mas objetos do tipo valor são destruídos quando o contexto que os contém é destruído, enquanto objetos do tipo referência são destruídos pelo coletor de lixo indefinidamente depois que a última referência a eles é removida".

Aqui, eu não gosto deste "tempo imprevisível". Embora eu mesmo admita que o coletor de lixo pode apagar o objeto de forma muito mais eficaz do que eu mesmo o apago no destruidor da classe que o criou.

Logicamente, como ninguém está se referindo a ele, significa que ninguém mais precisa do objeto, ele será apagado na próxima coleta de lixo. O tempo é imprevisível, embora você possa pedir à GC que o construa imediatamente. Mas isto também é um pedido, não uma ordem ))))

 
Georgiy Merts:

Não estou dizendo que o coletor de lixo vai apagar um objeto vivo ou um ponteiro. Estou dizendo que ele o removerá quando quiser.

Sharp tem uma função para proteger o objeto de ser apagado pelo coletor de lixo.

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:

E agora você está tentando desesperadamente inventar desculpas porque você não sabia disso ;)

Que diferença faz se eles o introduziram imediatamente ou meses depois? Você não teria sabido se eu não lhe tivesse dito).

Tenho medo de arder de vergonha, mas não sabia de & & & até recentemente, até que o vi no fxsaber em algum lugar. Eu usaria GetPointer de outra forma.

Mas prestei atenção à ausência de possibilidade de sobrecarregar algumas operações com objetos em algum lugar em setembro e, naquela época, tentei resolver este problema sozinho e algumas pessoas me escreveram que tal possibilidade não existe. E agora acontece que ela existe, então me pergunto quando exatamente ela apareceu (e por que não está na ajuda).

 
SemenTalonov:

Provavelmente, eles irão na direção do C# onde "código gerenciado" não tem ponteiros e tudo tem um objeto, mesmo tipos simples bool int duplo, etc.

Isso seria bom, mas é improvável que mudem alguma coisa nessa direção, pois é uma mudança completa no conceito da linguagem terminal, e tais coisas raramente são feitas.

SemenTalonov:

Exatamente de acordo com a IMHO é necessário não esquecer com o que exatamente você lida (objeto ou ponteiro para ele).

Para não esquecer, você deve decidir com certeza no início quando usar objetos e quando usar apontadores (idealmente nunca objetos e sempre apontadores).

E é bobagem escrever cada vez mais cartas para isso (especialmente para se preocupar com parênteses).

Além disso, neste caso, a operação de atribuição descrita por você não é utilizada em relação a um objeto, mas a seu campo não-objeto o que, em princípio, exclui a probabilidade de um erro (o tipo de ponteiro em tal operação não importa).

 
Ilya Malev:

Para não esquecer, você deve decidir exatamente no início quando usar objetos e quando usar apontadores (idealmente - nunca objetos e sempre apontadores).

Quando você abre seu próprio código após um tempo (um ou dois anos) e se repreende por não ter deixado comentários nos lugares "delicados", ou se não consegue distinguir objetos de ponteiros, é como uma perda total. Também não concordo que devemos recusar o uso de autoobjetos. O uso deles torna o código compacto e reduz a preocupação com o destino do objeto depois que ele se torna obsoleto. Além disso, tenho certeza que a vida útil de tal objeto é conhecida pelo compilador de antemão e, portanto, o compilador pode fornecer um código mais otimizado do que em caso de criação dinâmica.

Ilya Malev:

E é uma bobagem escrever cartas adicionais a cada vez para isso (especialmente para se preocupar com parênteses).

Além disso, no caso que você descreve, a operação de atribuição não é usada em relação a um objeto, mas a seu campo não-objeto o que basicamente exclui uma probabilidade de erro (o tipo de ponteiro em tal operação não importa).

Este absurdo vem do fato de que na MQL não há outra maneira de denotar o acesso a um objeto por um ponteiro. Em C/C++, é claro, seria mais lacônico.

pA->iValue

A razão da ausência da seta é provavelmente a mesma que a do"*" originalmente (desconhecido). No Qt (e provavelmente também no VS), o editor substitui automaticamente '.' por '->' se o objeto for acessado através de um ponteiro, ou seja, sem nenhum trabalho extra. Não tenho dúvidas de que a MQ pode acrescentar tal funcionalidade ao editor, se desejar. Acontece que, neste exemplo, o único sinal de se lidar com um ponteiro é o prefixo 'p' no nome. E isso é só porque não esqueci. Se todos são tão "tato" então tudo bem))

Isto é, fragmentos de código potencialmente perigosos devem ser marcados explicitamente. Não é preciso lembrar-se deles, é preciso vê-los. A necessidade de tal "formalização de relações" com objetos seria mais clara em amostras mais complicadas do que as dadas acima. Por exemplo, quando o próprio membro da classe é um ponteiro para alguma coisa.

Ao fornecer uma maneira uniforme de lidar comPOINTER_AUTOMÁTICO ePOINTER_DYNAMIC, nos é dada a idéia enganosa de que esses tipos de ponteiros são semelhantes. Mas na verdade são entidades diferentes e requerem tratamento diferente. Este é o assunto principal deste ramo.O mais óbvio é claro: enquantoPOINTER_AUTOMÁTICO sempre aponta para um objeto real,POINTER_DYNAMIC também pode estar vazio.

E vou apenas lembrá-lo de todas as diferentes variações de acesso aos dados (embora C/C++, desde que nossos caminhos coincidam)

OperadorSintaxeRecarregávelImplementado emCExemplo
Membro do tipo TDefinição fora da classe
Acesso a um elemento de matriza[b]SimSimRT::operador[](Sb);
n/d
Referência indireta ("objeto apontadopor a")*aSimSimRT::operador*();R operador*(Ta);
Referência ("endereçoa")& aSimSimR operadorT::operador&();R operador&(Ta);
Referindo-se a um membro da estrutura ("o membro b do objeto apontado pora")a-> bSimSimR*T::operador->();[nota 5];[nota 5]; [nota 6].
N/A
Referência a um membro de uma estrutura ("b membro do objetoa")a. bNãoSimn/d
Membro apontado por b em um objeto apontado pora[nota 6]a->*bSimNãoR operadorT::operador->*(Sb);R operador->*(Ta, Sb);
O membro apontado por b no objetoaa.*bNãoNãoN/A
 
SemenTalonov:

Bem, o mais óbvio é claro: sePOINTER_AUTOMÁTICO aponta sempre para um objeto real,POINTER_DYNAMIC também pode estar vazio.

Se o "mais óbvio" já é falso, vale a pena considerar seriamente e responder a tudo o resto?

POINTER_AUTOMÁTICO não é o tipo de variável, é o seu status. No momento seguinte, seu status pode ser bem diferente. Incluindo o POINTER_INVALID, é claro.
 
Ilya Malev:

Se o "mais óbvio" já é falso, vale a pena considerar seriamente e responder a tudo o mais?

Gostaria de esclarecimento sobre isso, se possível.

 
Ilya Malev:
POINTER_AUTOMÁTICO não é um tipo de variável, mas seu status. No momento seguinte, seu status pode ser bem diferente

Certamente não é um tipo. Você quer dizer que o auto-objeto torna-se um ponteiro com o statusPOINTER_DYNAMIC, por exemplo? O que se quer dizer é ostatusPOINTER_INVALID ao declarar um ponteiro, por exemplo.

 
SemenTalonov:

Gostaria de alguns esclarecimentos sobre isto, se possível.

É que em MCL aparentemente não é o mesmo que em C++. Aqui um ponteiro não é um tipo de dado separado, portanto ambos são objetos e uma variável contém seu cabo. Uma variável tem uma propriedade constante oculta (se declarada sem *), mas isso não a torna essencialmente uma variável de tipo diferente, apenas proíbe a atribuição de um cabo diferente a ela.

 

Ou seja, declarar

   A* const b=new A;

E você terá exatamente o mesmo "auto-objeto", somente você mesmo o apagará