ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

         
     
    Присвоєння і Ініціалізація
         

     

    Інформатика, програмування

    Присвоєння і Ініціалізація

    Розглянемо дуже простий клас строк string:

    struct string (

    char * p;

    int size;// розмір вектора, на який вказує p

    string (int sz) (p = new char [size = sz];)

    ~ string () (delete p;)

    );

    Рядок - це структура даних, що складається з вектора символів і довжини цього вектора. Вектор створюється конструктором і знищується деструкторами. Однак це може призвести до неприємностей.

    Наприклад:

    void f ()

    (

    string s1 (10);

    string s2 (20);

    s1 = s2;

    )

    буде розміщувати два вектори символів, а присвоювання s1 = s2 буде псувати вказівник на один з них і дублювати інший. На виході з f () для s1 і s2 викликатиметься деструктор і знищувати один і той же вектор з непередбачувано руйнівними наслідками. Вирішення цієї проблеми полягає в тому, щоб відповідним чином визначити присвоювання об'єктів типу string:

    struct string (

    char * p;

    int size;// розмір вектора, на який вказує p

    string (int sz) (p = new char [size = sz];)

    ~ string () ( delete p;)

    void operator = (string &)

    );

    void string:: operator = (string & a)

    (

    if (this == & a) return;// остерігатися s = s;

    delete p;

    p = new char [size = a.size];

    strcpy (p, a.p);

    )

    Це визначення string гарантує, і що попередній приклад буде працювати як передбачалося. Однак невелика зміна f () призведе до появи тієї ж проблеми в новому вигляді:

    void f ()

    (

    string s1 (10);

    s2 = s1;

    )

    Тепер створюється тільки один рядок, а знищується два. До неініціалізовані об'єкту певна користувачем операція присвоювання не застосовується. Швидкий погляд на string:: operator = () пояснює, чому було нерозумно так робити: вказівник p міститиме невизначене і абсолютно випадкове значення. Часто операція привласнення покладається на те, що її аргументи ініціалізований. Для такої ініціалізації, як тут, це не так за визначенням. Отже, потрібно визначити схожу, але іншу, функцію, щоб обробляти ініціалізацію:

    struct string (

    char * p;

    int size;// розмір вектора, на який вказує p

    string (int sz) (p = new char [size = sz];)

    ~ string () ( delete p;)

    void operator = (string &)

    string (string &);

    );

    void string:: string (string & a)

    (

    p = new char [size = a.size];

    strcpy (p, a.p);

    )

    Для типу X ініціалізацію тим же типом X обробляє конструктор X (X &). Не можна не підкреслити ще раз, що присвоювання і ініціалізація - різні дії. Це особливо важливо при описі деструктора. Якщо клас X має конструктор, що виконує нетривіальну роботу на зразок звільнення пам'яті, то швидше за все буде потрібно повний комплект функцій, щоб повністю уникнути побітового копіювання об'єктів:

    class X (

    // ...

    X (something);// конструктор: створює об'єкт

    X (& X);// конструктор: копіює в ініціалізації

    operator = (X &);// присвоювання: чистить і копіює

    ~ X ();// деструктор: чистить

    );

    Є ще два випадки, коли об'єкт копіюється: як параметр функції і як повертається значення. Коли передається параметр, ініціалізується неініціалізовані до цього мінлива - формальний параметр. Семантика ідентична семантиці ініціалізації. Те ж саме відбувається при поверненні з функції, хоча це менш очевидно. В обох випадках буде застосований X (X &), якщо він визначений:

    string g (string arg)

    (

    return arg;

    )

    main ()

    (

    string s = "asdf";

    s = g (s);

    )

    Ясно, що після виклику g () значення s зобов'язане бути "asdf". Копіювання значення s в параметр arg складності не представляє: для цього треба кликати string (string &). Для взяття копії цього значення з g () потрібно ще один виклик string (string &); на цей раз ініціалізіруемой є тимчасова змінна, яка потім присвоюється s. Такі змінні, природно, знищуються як годиться за допомогою string:: ~ string () при першій нагоді.

    Список літератури

    Для підготовки даної роботи були використані матеріали з сайту http://www.realcoding.net

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status