MQL5 Il compilatore non distingue tra una classe e un puntatore ad essa - pagina 12

 
Georgiy Merts:

No. Chiaramente, in questo caso, la variabile deve essere cancellata all'uscita dal blocco.

Sto parlando di oggetti creati da nuovi:

Lo standard C# specifica:"Sia gli oggetti di tipo valore, come le strutture, che gli oggetti di tipo riferimento, come le classi, vengono distrutti automaticamente, ma gli oggetti di tipo valore vengono distrutti quando il contesto che li contiene viene distrutto, mentre gli oggetti di tipo riferimento vengono distrutti dal raccoglitore di rifiuti indefinitamente dopo che l'ultimo riferimento ad essi viene rimosso".

Ecco, non mi piace questo "tempo imprevedibile". Anche se ammetto che il raccoglitore di rifiuti può eliminare l'oggetto in modo molto più efficace di quanto io stesso elimini l'oggetto nel distruttore della classe che l'ha creato.

Logicamente, dato che nessuno lo sta referenziando significa che nessuno ha più bisogno dell'oggetto, sarà cancellato alla prossima raccolta dei rifiuti. Il tempo è imprevedibile, anche se si può chiedere a GC di costruirlo immediatamente. Ma anche questa è una richiesta, non un ordine )))

 
Georgiy Merts:

Non sto dicendo che il raccoglitore di rifiuti cancellerà un oggetto vivo o un puntatore. Sto dicendo che lo rimuoverà quando vorrà.

Sharp ha una funzione per proteggere l'oggetto dall'essere cancellato dal raccoglitore di rifiuti.

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 ora stai cercando disperatamente di inventare delle scuse per cui non ne eri a conoscenza ;)

Che differenza fa se l'hanno introdotto subito o mesi dopo? Non l'avresti saputo e non lo sapresti ancora se non te l'avessi detto).

Ho paura di bruciare dalla vergogna, ma non sapevo di & & fino a poco tempo fa, finché non l'ho visto su fxsaber da qualche parte. Altrimenti userei GetPointer.

Ma ho prestato attenzione all'assenza di possibilità di sovraccaricare alcune operazioni con oggetti in settembre da qualche parte e allora ho cercato di risolvere questo problema da solo e alcune persone mi hanno scritto che tale possibilità non esiste. E ora si scopre che esiste, quindi mi chiedo quando esattamente è apparso (e perché non è nella guida).

 
SemenTalonov:

Probabilmente, andranno nella direzione di C# dove il "codice gestito" non ha puntatori e tutto ha un oggetto, anche i semplici tipi bool int double, ecc.

Sarebbe bello, ma è improbabile che cambino qualcosa in questa direzione, perché è un cambiamento completo nel concetto di linguaggio terminale, e queste cose vengono fatte raramente.

SemenTalonov:

Esattamente secondo IMHO è necessario non dimenticare con cosa si ha a che fare esattamente (oggetto o puntatore ad esso).

Per non dimenticare, dovete decidere all'inizio con certezza quando usate oggetti e quando usate puntatori (idealmente mai oggetti e sempre puntatori).

Ed è sciocco scrivere ogni volta lettere extra per questo (specialmente preoccuparsi delle parentesi).

Inoltre, in questo caso, l'operazione di assegnazione da voi descritta non è usata in relazione a un oggetto ma al suo campo non oggetto, il che, in linea di principio, esclude una probabilità di errore (il tipo di puntatore in tale operazione non ha importanza).

 
Ilya Malev:

Per non dimenticare, dovete decidere esattamente all'inizio quando usate oggetti e quando usate puntatori (idealmente - mai oggetti e sempre puntatori).

Quando apri il tuo codice dopo molto tempo (un anno o due) e ti rimproveri di non aver lasciato commenti nei posti "delicati", o se non sai distinguere gli oggetti dai puntatori, è come una perdita totale. Non sono nemmeno d'accordo sul fatto di rifiutare l'uso degli autoobject. Usarli rende il codice compatto e riduce la preoccupazione per il destino dell'oggetto dopo che è diventato obsoleto. Inoltre, sono sicuro che la durata di un tale oggetto è nota al compilatore in anticipo e quindi il compilatore può fornire un codice più ottimizzato che in caso di creazione dinamica.

Ilya Malev:

Ed è semplicemente stupido scrivere lettere aggiuntive ogni volta per questo (specialmente per preoccuparsi delle parentesi).

Inoltre, nel caso che descrivi, l'operazione di assegnazione non è usata rispetto a un oggetto ma al suo campo non oggetto, il che esclude fondamentalmente la probabilità di un errore (il tipo di puntatore in tale operazione non ha importanza).

Questa assurdità deriva dal fatto che in MQL non c'è altro modo per indicare l'accesso ad un oggetto tramite un puntatore. In C/C++, naturalmente, sarebbe più laconico.

pA->iValue

La ragione dell'assenza della freccia è probabilmente la stessa che per il'*' in origine (sconosciuto). In Qt (e probabilmente anche in VS), l'editor sostituisce automaticamente '.' con '->' se si accede all'oggetto attraverso un puntatore, cioè senza alcun lavoro extra. Non ho dubbi che MQ possa aggiungere tale funzionalità all'editor, se lo desidera. Come si scopre, in questo esempio l'unico segno di avere a che fare con un puntatore è il prefisso 'p' nel nome. E questo solo perché non l'ho dimenticato. Se tutti sono così "tattili" allora va bene))

Cioè i frammenti di codice potenzialmente pericolosi dovrebbero essere esplicitamente contrassegnati. Non bisogna ricordarli, bisogna vederli. La necessità di tale "formalizzazione delle relazioni" con gli oggetti sarebbe più chiara su campioni più complicati di quelli dati sopra. Per esempio, quando un membro della classe stessa è un puntatore a qualcosa.

Fornendo un modo uniforme di trattarePOINTER_AUTOMATIC ePOINTER_DYNAMIC, ci viene data l'idea fuorviante che questi tipi di puntatori siano simili. Ma di fatto sono entità diverse e richiedono un trattamento diverso.Questo è l'argomento principale di questo ramo. Ilpiù ovvio è naturalmente: mentrePOINTER_AUTOMATIC punta sempre a un oggetto reale,POINTER_DYNAMIC può anche essere vuoto.

E vi ricorderò tutte le diverse varianti di accesso ai dati (anche se C/C++, purché i nostri percorsi coincidano)

OperatoreSintassiRicaricabileImplementato inCEsempio
Membro del tipo TDefinizione fuori dalla classe
Accedere a un elemento dell'arraya[b]RT::operator[](Sb);
n/a
Riferimento indiretto ("oggetto indicatoda a")*aRT::operator*();R operatore*(Ta);
Riferimento ("indirizzoa")& aR operatoreT::operator&();R operatore&(Ta);
Fare riferimento a un membro della struttura ("il membro b dell'oggetto indicato daa")a-> bR*T::operator->();[nota 5]
N/A
Riferimento a un membro di una struttura ("b member of objecta")a. bNon/a
Membro indicato da b in un oggetto indicato daa[nota 6]a->*bNoR operatoreT::operator->*(Sb);Operatore R->*(Ta, Sb);
Il membro indicato da b nell'oggettoaa.*bNoNoN/A
 
SemenTalonov:

Beh, il più ovvio naturalmente: sePOINTER_AUTOMATIC punta sempre a un oggetto reale, alloraPOINTER_DYNAMIC può anche essere vuoto.

Se il "più ovvio" è già falso, vale la pena considerare seriamente e rispondere a tutto il resto?

POINTER_AUTOMATIC non è il tipo di variabile, è il suo stato. Il momento successivo il suo stato può essere molto diverso. Compreso POINTER_INVALID, ovviamente.
 
Ilya Malev:

Se il "più ovvio" è già falso, vale la pena considerare seriamente e rispondere a tutto il resto?

Vorrei un chiarimento su questo, se possibile

 
Ilya Malev:
POINTER_AUTOMATIC non è un tipo di variabile ma il suo stato. Nel momento successivo, il suo stato può essere molto diverso

Certamente non è un tipo. Vuoi dire che l'auto-oggetto diventa un puntatore con lo statoPOINTER_DYNAMIC, per esempio? Ciò che si intende qui è lostatoPOINTER_INVALID, per esempio, quando si dichiara un puntatore.

 
SemenTalonov:

Vorrei qualche chiarimento su questo, se possibile.

È solo che in MKL apparentemente non è lo stesso che in C++. Qui un puntatore non è affatto un tipo di dati separato, quindi entrambi sono oggetti e una variabile contiene il suo handle. Una variabile ha una proprietà costante nascosta (se dichiarata senza *), ma questo non la rende essenzialmente una variabile di tipo diverso, ma vieta solo di assegnarle un handle diverso.

 

Cioè dichiarare

   A* const b=new A;

E avrete esattamente lo stesso "auto-oggetto", solo che lo cancellerete voi stessi