kopiowanie obiektów - problem z operatorem przypisania

0

Dzień dobry. Dzisiaj na zajęciach nauczyciel pokazywał przykłady z kopiowaniem obiektów, w tym taki:

#include <iostream>
#include <string>
#include <windows.h>

class Osoba
{
public:
    Osoba()
    {
        this->imie = NULL;
    }
    Osoba(const Osoba & osoba)
    {
        this->imie = NULL;
        this->SetImie(osoba.imie);
    }
    ~Osoba()
    {
        Clean();
    }

    void SetImie(char *imie)
    {
        Clean();
        this->imie = new char[strlen(imie) + 1];
        strcpy(this->imie, imie);
    }

    char * GetImie()
    {
        return this->imie;
    }
 
private:
    char * imie;
    void Clean()
    {
        if (imie != NULL)
            delete imie;
        imie = NULL;
    }
}; 

int main()
{
 	Osoba osoba;

	osoba.SetImie("JAN");
	std::cout << osoba.GetImie() << std::endl; 

	{
		Osoba kopia;
		kopia = osoba;
		std::cout << "kopia: " << kopia.GetImie() << std::endl;
	}

    return 0;
}

Stwierdził, że kod klamrach w mainie nie zadziała, chyba że zdefiniujemy operator przypisania. No to do klasy dodałem taki kod:

Osoba & operator =(const Osoba & ref)
{
	return *this;
}

po uruchomieniu programu niestety wyrzuca błąd "read access violation. _First was nullptr.". W debuggerze znalazłem, że 'imie' dla obiektu 'kopia' jest równe NULL. W związku z tym mam pytanie, co z tym kodem jest nie tak? Czy to źle zdefiniowany operator przypisania czy może coś z konstruktorem kopiującym?

1

W operatorze przypisania nic nie przypisujesz, co tu może być nie tak? :​)

Osoba & operator =(const Osoba & ref)
{
    imie = new char[strlen(ref.imie) + 1];
    strcpy(imie, ref.imie);
    return *this;
}

Przy okazji, masz w kodzie UB i tak - new[] powinno mieć swoje delete[], a Ty używasz delete.

A tak w ogóle, to zapraszam do lektury: https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/ Może to i przykład edukacyjny, ale wiedz, aby nigdy¹ takich rzeczy w produkcyjnym kodzie nie pisać.

¹ no, prawie, ale wtedy będziesz miał to podparte dziesiątką benchmarków i kilkoma code review.

2

Na przyszłość dodam tylko, że if tutaj jest niepotrzebny. Operator delete sam sobie sprawdzi czy wskaźnik nie jest nullem (w uproszczeniu).

if (imie != NULL)
    delete imie;

1 użytkowników online, w tym zalogowanych: 0, gości: 1