Выбрать главу

    Student fn( ) ; /* Возвращает объект по значению */

    int main ( int argcs , char* pArgs[ ] )

    {

        Student s ;

        s = fn( ) ; /* В результате вызова fn( ) будет создан временный объект */

        return 0 ;

    }

Функция fn( ) возвращает объект по значению. В конечном счёте этот объект будет скопирован в s, но где он находится до этого?

Для хранения таких объектов С++ создаёт временные объекты ( такие объекты создаются и в некоторых других случаях ). "Хорошо, — скажете вы, — С++ создаёт временные объекты, но откуда он знает, когда их надо уничтожать?" ( Спасибо за хороший вопрос! ) В нашем примере это не имеет особого значения, поскольку временный объект выйдет из области видимости, как только копирующий конструктор скопирует его в s. Но что, если s будет определено как ссылка?

_________________

221 стр. Глава 18. Копирующий конструктор

    int main ( int argcs , char* pArgs[ ] )

    {

        Student& refS = fn( ) ;

        /* ...Что теперь?... */

        return 0 ;

    }

Теперь период жизни временного объекта имеет большое значение, поскольку ссылка refS продолжает своё существование независимо от существования объекта! В приведённом ниже примере я отметил место, начиная с которого временный объект становится недоступен.

    Student fn1( ) ;

    int fn2( Student& ) ;

    int main ( int argcs , char* pArgs[ ] )

    {

        int x ;

        /* Создаём объект Student, вызывая fn1( ), а затем передаём этот объект функции fn2( ) . fn2( ) возвращает целочисленное значение, которое используется для выполнения некоторых вычислений. Весь этот период временный объект, возвращённый функцией fn1( ), доступен */

        х = 3*fn2( fn1( ) ) + 10 ;

        /* Временный объект, который вернула функция fn1( ), становится недоступен */

        /* ...Остальной код... */

        return 0 ;

    }

Таким образом, пример с использованием ссылки неверен, поскольку объект выйдет из области видимости, a refS будет продолжать существовать, и в результате ссылка будет указывать на несуществующий объект.

Как избегать временных объектов...222

Вы можете подумать, что изучение всего этого копирования объектов туда и обратно — пустая трата времени. Что, если вы не хотите делать все эти копии? Самое простое решение заключается в передаче и приёме объектов функции по ссылке. Это исключает все описанные неприятности.

Но как убедиться, что С++ не создаёт временных объектов незаметно для вас? Допустим, ваш класс использует ресурсы, которые вы не хотите копировать. Что же вам делать?

Можно просто использовать вывод сообщения в копирующем конструкторе, которое предупредит вас о том, что была сделана копия. А можно объявить копирующий конструктор защищённой функцией, как показано в приведённом ниже примере.

    class Student

    {

    protected :

        Student( Student& s ){ }

    public :

        /* ...Всё остальное как обычно... */

    } ;

Такой подход исключит использование копирующего конструктора любыми внешними функциями, включая сам С++, а значит, запретит создание копий ваших объектов Student ( позволяя при этом создавать копии функциям-членам ).

_________________

222 стр. Часть 3. Введение в классы

Аргумент копирующего конструктора...223

Использование копирующего конструктора для создания временных объектов и копий объектов вызывает один интересный вопрос. Рассмотрим очередной пример.

    class Student

    {

    public :

        Student( Student s )

        {

            /* ...всё, что угодно... */

        }