VS i konstruktor kopiujący

0

Witam

Chciałem was zapytać dlaczego po skompilowaniu tego kodu pod Visualem(testowane na 2008 i 2013 x64) "opcja2" odpala mi konstruktor kopiujący i destruktor ? Ten sam kod pod g++:

[[email protected] ~]$ g++ -v
Using built-in specs.
Target: i386-undermydesk-freebsd
Configured with: FreeBSD/i386 system compiler
Thread model: posix
gcc version 4.2.1 20070831 patched [FreeBSD]

wydaje się działać normalnie - printscreen w załączniku

#include <string>
#include <iostream>

using namespace std;

class Seks
{
private:
    string zKim;
    char *zKimTab;
    int sizeTab;
    static int ileRazy;

public:
    Seks(double dziewczyny);
    Seks();
    Seks(const char *kto);
    Seks(string* kto);
    Seks(const string kto);
    Seks(const Seks &);
    ~Seks();

};

int Seks::ileRazy = 0;
Seks::Seks(const char *ktoTab)
{
    cout << "6. Seks::Seks(const char *ktoTab)" << endl;
    size_t size = strlen(ktoTab);
    zKimTab = new char[size + 1];
    memset(zKimTab, 0, size + 1);
    memcpy(zKimTab, ktoTab, size);

    sizeTab = size + 1;

    ileRazy++;
}

Seks::Seks()
{

    cout << "1. Seks::Seks()" << endl;
    ileRazy++;
    zKimTab = NULL;
}

Seks::Seks(const string kto) : zKim(kto)
{
    cout << "7. Seks::Seks(const string kto)" << endl;
    ileRazy++;
    zKimTab = NULL;
}

Seks::Seks(string *kto) : zKim(*kto)
{
    cout << "2. Seks::Seks(string &kto)" << endl;
    ileRazy++;
    zKimTab = NULL;
}

Seks::Seks(const Seks &seksorg)
{
    cout << "3. Seks::Seks(const Seks &) - k. kopiujacy" << endl;
    if (seksorg.zKimTab != NULL)
    {
        sizeTab = seksorg.sizeTab;
        zKimTab = new char[sizeTab + 1];

        memset(zKimTab, 0, sizeTab + 1);
        memcpy(zKimTab, seksorg.zKimTab, sizeTab);
    }

}

Seks::~Seks()
{
    if (zKimTab != NULL)
    {
        delete[] zKimTab;
        sizeTab = 0;
        zKimTab = NULL;
    }

    ileRazy--;
    zKim = "";
    cout << "4. Seks::~Seks()" << endl;
}

Seks::Seks(double dziewczyny)
{

    cout << "5. Seks::Seks(double dziewczyny)" << endl;
    ileRazy++;
    zKimTab = NULL;
}

int main(void)
{
    int breakpoint = 0;

    {
    cout << "-- Opcja 1: --" << endl;
    char *napis = "aaaa";
    Seks sx1 = Seks(napis);
    breakpoint = 0; // a) ustaw tu breakpointa. co się pojawi i dlaczego tak?

    cout << "-- Opcja 2: --" << endl;
    const string fl = "opcja2";
    Seks sx2 = Seks(fl); 
    breakpoint = 0; 
    //b) ustaw tu breakpointa. co się pojawi i dlaczego tak ?
    // Wywola sie konstruktor kopiujacy ponieważ ?

    cout << "-- Opcja 3: --" << endl;
    string *ptr = new string("opcja3");
    Seks sx3 = Seks(ptr); 
    breakpoint = 0; // b) ustaw tu breakpointa. co się pojawi i dlaczego tak ? 
    delete ptr; // mozemy usunac bo juz mamy kopie stringu  "opcja3" w sx3, dzieki: Seks::Seks(string *kto) : zKim(*kto)

    cout << "-- Opcja 4 --" << endl;
    Seks sx4;
    breakpoint = 0; // c) ustaw tu breakpointa. co się pojawi i dlaczego tak ? // jasne

    cout << "-- Opcja 5: --" << endl;
    Seks sx5 = Seks(2);
    breakpoint = 0; // d) ustaw tu breakpointa. co się pojawi i dlaczego tak ? // jasne

    cout << "-- Opcja 6: --" << endl;
    cout << "Tworze obiekt *: " << endl;
    Seks *sx6 = new Seks("XXX");
    breakpoint = 0; // f1) ustaw breakpointa. co sie pojawi i dlaczego ? // jasne
    cout << "Usuwam obiekt *: " << endl;
    delete sx6;
    breakpoint = 0; // f2) ustaw breakpointa. co sie pojawi i dlaczego ? // jasne
}

    return 0;
}

Dzięki
Dawid

0
Seks::~Seks()
{
    if (zKimTab != NULL)
    {
        delete[] zKimTab;

Na tym się kod wywala, bo zKimTab było niezainicjalizowane (nie jest więc NULLem) i zawiera śmieci.

Jedyna możliwość że zKimTab pozostaje niezaincjalizowane, to niespełniony warunek w konstruktorze kopiującym:

    if (seksorg.zKimTab != NULL)

To znaczy że dochodzi do kopii pustego obiektu, a konstruktor nie jest na to odporny.
Najlepiej wyrzuć ten warunek po prostu, bo tylko szkodzi.

Konstruktor kopiujący wywoływany jest tutaj:

   Seks sx2 = Seks(fl);

To jest implementation dependent, czy zostanie wywołany k.kopiujący w tym przypadku, czy nie.
W przypadku Visuala, zniknie ci kopiowanie gdy skompilujesz kod z optymalizacją /Ox.

Najlepiej napisz po prostu:

    Seks sx2(fl);

I masz gwarantowany brak kopii.

0

Tą tablice znaków zrobiłem na szybko i "byle jak" także nie zadbałem o resztę. Chodziło mi bardziej sprawdzenie czemu tak a nie inaczej w kwestii cctor'a.

Konstruktor kopiujący wywoływany jest tutaj:
Seks sx2 = Seks(fl);

Przeanalizowałem to sobie w paint'cie ;D (printscreen w załączniku) zaraz po utworzeniu tego tematu... i drugie pytanie jakie miałem zadać to czemu akurat dla "opcja2" kompilator VS wykonuje cctor`a a obiekty: sx1, sx3, sx5 tworzy normalnie. Rozumiem dlatego, że je dobrze zoptymalizował ?

O pojęciu "implementation dependent" poczytam.

0

i zapomniałem podziękować.

Dzięki Azarien :-)

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