NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: hlboka kopia

V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
expoox
Tvůrce
Avatar
expoox:24.4.2016 9:05

Ahoj, potrebujem v programe robit hlboku kopiu u copy constructor a aj som si myslel ze ju robim ale zrejme nie, neviete mi prosim povedat preco to robi plytku ?

class CData
{
    private:
        uint32_t version;
        uint8_t block[BLOCK_SIZE];

    public:
        CData(void) {version = 0;}
        ....
        CData & operator=(const CData & a){
            version = a.version;
            for (int i = 0; i < BLOCK_SIZE; i++)
                block[i] = a.block[i];

            return *this;
        }
};

struct ver
{
        CData * binFileArch;
        uint32_t usedArch;
        uint32_t actualSizeArch;
        uint32_t posArch;
};

class CFile
{
...
    private:
        CData * binFile;
        uint32_t used;
        uint32_t actualSize;
        uint32_t pos;

        ver * backUp;
        uint32_t numOfBackUps;
};

CFile::CFile (void) {
    used = 0;
    binFile = new CData[SIZE];
    actualSize = SIZE;
    pos = 0;
    numOfBackUps = 1;
    backUp = new ver[BACKUP_SIZE];
    for (uint32_t i = 0; i < BACKUP_SIZE; i++)
        backUp[i].binFileArch = new CData[SIZE];

}

CFile::CFile (const CFile & a) {     // kopirujuci konstruktor
    binFile = new CData[SIZE];
    binFile = a.binFile;
    used = a.used;
    actualSize = a.actualSize;
    pos = a.pos;
    numOfBackUps = a.numOfBackUps;
    backUp = new ver[BACKUP_SIZE];
    for (uint32_t i = 0; i < BACKUP_SIZE; i++)
        backUp[i].binFileArch = new CData[SIZE];

    for (uint32_t i = 0; i < a.numOfBackUps; i++){
        backUp[i].actualSizeArch = a.backUp[i].actualSizeArch;
        backUp[i].posArch = a.backUp[i].posArch;
        backUp[i].usedArch = a.backUp[i].usedArch;
        *(backUp[i].binFileArch) = *(a.backUp[i].binFileArch);
    }
}
 
Odpovědět
24.4.2016 9:05
Avatar
B42P6
Člen
Avatar
Odpovídá na expoox
B42P6:24.4.2016 13:45

Ahoj, nepozrel som sa na to veľmi presne, ale vidím tam jednu chybu:

binFile = new CData[SIZE];
binFile = a.binFile;

Na to, prečo to je chyba a ako ju opraviť musíš prísť sám.

Nahoru Odpovědět
24.4.2016 13:45
'long long long' is too long for GCC
Avatar
expoox
Tvůrce
Avatar
Odpovídá na B42P6
expoox:24.4.2016 14:30

bolo to toto, vsak ?

(*binFile) = (*a.binFile);
 
Nahoru Odpovědět
24.4.2016 14:30
Avatar
B42P6
Člen
Avatar
Odpovídá na expoox
B42P6:24.4.2016 17:28

Ehm... nie. binfile je ukazateľ. Takže toto:

binFile = new CData[SIZE];

Alokuje novú pamäť a ukazateľ na ňu uloží do binFile.

A toto:

binFile = a.binFile;

uloží do binFile ukazateľ na a.binFile. Čiže si natrvalo stratil pamäť ktorú si alokoval (pretože si prepísal hodnotu v binFile) čím vzniká memory leak a binfile teraz ukazuje na a.binFile, čiže každá operácia s týmto ukazateľom zmení aj hodnoty v druhej triede.
Riešenie: musíš skopírovať celé dynamické pole (tak ako si to urobil s backUp)

BTW: Urob si v projekte poriadok (prípadne si ho lepšie navrhni) je tam veľa ďalších chýb , napr:

Tu alokuješ dynamické pole:

backUp[i].binFileArch = new CData[SIZE];

A tu potom len zmeníš prvý prvok:

*(backUp[i].binFileArch) = *(a.backUp[i].binFileArch);
Nahoru Odpovědět
24.4.2016 17:28
'long long long' is too long for GCC
Avatar
expoox
Tvůrce
Avatar
Odpovídá na B42P6
expoox:24.4.2016 18:42

no ale

binFile = a.binFile;

by malo podla mna zavolat pretazeny operator= triedy CData (to iste aj v druhom pripade co popisujes) a tak riesit presne toto, ci to chapem zle ?

 
Nahoru Odpovědět
24.4.2016 18:42
Avatar
B42P6
Člen
Avatar
Odpovídá na expoox
B42P6:24.4.2016 19:02

Nie, nezavolá pretažený operátor= na toto si sa pýtal už tu: http://www.itnetwork.cz/…71b5588cc3b9#…
A aj keby si na tom zavolal pretažený operátor:

*binFile = *a.binFile;

Čo by sa tým vyriešilo?
binFile je ukazateľ na dynamické pole, a ty meníš len prvý prvok v tomto poli (presne rovnaký problém som popísal v predošlom príspevku). Skús si precvičiť ukazatele, dynamickú alokáciu, atd... . Pretože v tom máš pravdepodobne nejasno.

Nahoru Odpovědět
24.4.2016 19:02
'long long long' is too long for GCC
Avatar
Veles
Člen
Avatar
Veles:16.5.2016 11:47

V konštruktoroch sa nevolá automaticky funkcia s operátorom priradenia, ak by si to chcel urobiť, tak tú funkciu tam musíš vypísať. čiže tvoj kód:

binFile = a.binFile;

Urobí to, čo napísal B42P6, ale keď napíšeš napr. do

int main()
{
        Trieda = Trieda2;
}

Tak vtedy sa sa zavolá funkcia s operátorom priradenia.

Ak by si chcel aby sa zavolala funkcia s operátorom priradenia, tak musíš spraviť toto:

binFile->operator=(a.binFile);

Ale tu som si nie istý, či to tak môže byť, pretože len nedávno som začal robiť s triedami.

 
Nahoru Odpovědět
16.5.2016 11:47
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 7 zpráv z 7.