Przejdź do treści
MQL5 · MetaTrader 5 · po polsku
kod odczarowany

MQL5 / Inżynieria

Struktury i klasy: kopia czy referencja

Struktura przekazana do funkcji jest kopiowana, obiekt klasy nie. Skąd biorą się zmiany, które znikają, i te, które pojawiają się nieoczekiwanie.

1 fragment kodu z tej strony przeszedł przez kompilator MetaEditor build 6090, 2026-08-05.

Programiści przychodzący do MQL5 z C++ często traktują słowa kluczowe struct i class jako synonimy, różniące się jedynie domyślnym modyfikatorem dostępu (public dla struktur, private dla klas). W C++ tak właśnie jest. W MQL5 jednak ta różnica jest fundamentalna i dotyczy samego modelu pamięci. Niezrozumienie tego faktu prowadzi do wycieków pamięci, błędów "dangling pointers" i drastycznych spadków wydajności.

W MQL5 struktury są typami wartościowymi (Value Types). Kiedy przypisujesz jedną strukturę do drugiej, MQL5 wykonuje głęboką kopię (deep copy) danych bit po bicie. Z kolei klasy są typami referencyjnymi (Reference Types). Klasa zawsze jest tworzona na stercie (heap) za pomocą new, a przypisanie obiektu do innej zmiennej kopiuje jedynie wskaźnik (adres) do tego samego obiektu w pamięci.

Struktury i klasy: kopia czy referencjaStruktura przekazana do funkcji jest kopiowana, obiekt klasy nie. Skąd biorą się zmiany, które znikają, i te, które pojawiają się nieoczekiwanie. Kopiowanie w MQL5: Struktura vs Klasa Struct (Kopia wartości) Struct A Struct B B = A tworzy nową kopię pamięci Zmiana B nie wpływa na A Class (Kopia referencji) Ptr A Ptr B Obiekt B = A kopiuje tylko wskaźnik Zmiana B wpływa na A! (Ten sam obiekt)

Pstryczek na stercie: Kiedy używać czego?

W MQL5 struktury nie mogą dziedziczyć po innych strukturach (mogą jedynie implementować interfejsy), nie mają wirtualnych funkcji i nie można użyć dla nich słowa new. Są idealne do lekkich kontenerów na dane. Klasyczne struktury z API MQL5, takie jak MqlTradeRequest czy MqlRates, to właśnie typy wartościowe. Przypisanie MqlRates rates1 = rates2 jest bezpieczne i szybkie, o ile struktura nie zawiera w sobie dynamicznych tablic.

Problem pojawia się, gdy w strukturze umieścimy tablicę dynamiczną (np. double arr[]). Wtedy kopia struktury skopiuje referencję do tej samej tablicy! Jest to tzw. płytka kopia (shallow copy). Modyfikacja elementów w tablicy w jednej strukturze zmieni je w drugiej.

// STRUKTURA - typ wartościowy
struct SConfig {
    int magic;
    double lot;
};

// KLASA - typ referencyjny
class CStrategy {
    int id;
public:
    CStrategy(int i) { id = i; }
    void PrintId() { Print("ID: ", id); }
};

void OnStart() {
    SConfig cfg1;
    cfg1.magic = 100;
    
    // Tworzy niezależną kopię. Bezpieczne.
    SConfig cfg2 = cfg1; 
    cfg2.magic = 200; // cfg1.magic wciąż wynosi 100!

    CStrategy *strat1 = new CStrategy(1);
    
    // Kopiuje WSKAŹNIK, nie sam obiekt!
    CStrategy *strat2 = strat1; 
    strat2 = new CStrategy(2); // strat1 nadal wskazuje na obiekt 1
    
    // Aby skopiować obiekt, trzeba napisać własny konstruktor kopiujący
    // lub przeciążyć operator przypisania (wymaga referencji &)
    
    delete strat1;
    delete strat2;
}