чем отличается присваивание от инициализации?

Рейтинг: 0Ответов: 2Опубликовано: 18.02.2023
class sample {
    char *s;
public:
    sample()
    {
        s = new char ('\0');
        cout << "Вызвался конструктор " <<this<< endl;
    }

    sample(const sample& obj)
    {
            s = new char[strlen(obj.s) + 1];
            strcpy_s(s, strlen(obj.s) + 1, obj.s);
            cout << "Конструктор копии" << this << endl;
    }

    ~sample()
    {
        cout << "Попытка вызвать деструктор " << this << endl;
        if (s) delete[] s;
        
    }
    void show() { cout << s << "\n"; }
    void set(char* str);
};


// Загрузка строки.
void sample::set(char* str)
{
    s = new char[strlen(str) + 1];
    strcpy_s(s, strlen(str) + 1, str);
}


 // Эта функция возвращает объект типа sample.
 sample input()
{
    char instr[80];
    sample str;
    cout << "Введите строку: ";
    cin >> instr;
    str.set(instr);
    return str;
}


int main()
{
    system("chcp 1251>0");
    srand(time(NULL));

    
    sample ob = input(); // чем отличается вот это


    //sample ob;

    //ob = input();// от этого? и почему этот вариант выдает ошибку?
    ob.show();

    return 0;
}

Ответы

▲ 0

Инициализация происходит один раз при вызове конструктора, присвоение - каждый раз при вызове оператора =.

На строке sample ob = input(); происходит инициализация (с использованием нежелательного синтаксиса copy initialization). Вместо этого во всех случаях следует использовать синтаксис direct list initialization sample ob{input()};.

На строке ob = input(); происходит присваивание. Оно заканчивается плохо, так как оператор = для класса не переопределен надлежащим образом для корректного обращения с динамически выделенной памятью. Для любых не POD классов оператор = следует либо определять, либо запрещать. см правило 0/3/5

▲ 0

Функция присваивания подразумевает аккуратно избавляться от текущего состояния объекта и присваивания нового.
Так как вы сами написали конструктор копирования, то оператор присваивания по-умолчанию не будет реалезован и вы должны сами его написать.
А-ля :

sample & sample :: operator = ( sample const & obj ) {
  
  // здесь и присутствует отличие от конструктора
  delete [ ] s ;

  s = new char[strlen(obj.s) + 1];
  strcpy_s(s, strlen(obj.s) + 1, obj.s);
  cout << "Оператор присваивания " << this << endl;
  return * this ;
}

плохую функцию set можете удалить.