Передача объектов в функцию и возврат объектов

Существует три способа передачи объекта в функцию:

  • передача копии. При этом способе изменение объекта внутри функции не затрагивает исходный объект. Обратите внимание на то, что в этом случае вызывается конструктор копирования, а не обычный конструктор. Это важно учитывать, когда внутри класса используется динамическое выделение памяти. Если конструктор копирования не определен, то выполняется побитовая копия объекта. Следует учитывать, что передача копии объекта в большинстве случаев является плохим решением, особенно если объект содержит много данных;
  • передача указателя на объект. Для этого при вызове функции перед названием переменной указывается оператор & (взятие адреса), а в прототипе функции объявляется указатель. В этом случае в функцию передается не значение переменной, а ее адрес, поэтому внутри функции можно изменить исходный объект. Для доступа к членам объекта используется оператор ->;
  • использование механизма ссылок. Этот способ используется наиболее часто, так как внутри функции переменная является псевдонимом исходного объекта. Любые изменения псевдонима отражаются на исходном объекте. Если внутри функции объект не должен изменяться, то его следует объявить константным. При использовании механизма ссылок перед названием переменной в объявлении и определении функции указывается оператор &, а при вызове — только название объекта. Для доступа к членам объекта используется оператор «точка».

В качестве значения функция может возвращать объект. В этом случае может создаваться временный объект, а когда результат присваивается экземпляру класса может выполняться копирование, при этом вызывается конструктор копирования, а не обычный конструктор. Это важно учитывать, когда внутри класса используется динамическое выделение памяти. Если компилятор поддерживает оптимизацию вариантов RVO или NRVO, то при возврате объекта временный объект не создается и конструктор копирования не вызывается (см. разд. 13.6). Пример передачи объектов в функцию и возврат объектов приведен в листинге 13.22.

Листинг 13.22. Передача объектов в функцию и возврат объектов

#include <iostream>

class Point {
public:
   int x, y;
   void dump() { std::cout << x << " " << y << std::endl; }
   Point(int a, int b)       // Обычный конструктор
      : x(a), y(b) {}
   Point(Point &obj)         // Конструктор копирования
      : x(obj.x), y(obj.y) {}
};
void func1(Point obj) {      // Передача копии
   std::cout << obj.x << " " 
        << obj.y << std::endl;
}
void func2(Point *p) {       // Передача указателя
   p->x = 4; p->y = 12;
}
Point func3(Point &p) {      // Механизм ссылок
   Point obj(p.x + 10, p.y + 20);
   return obj;               // Возврат объекта
}

int main() {
   Point point(10, 20);      // Объявление объекта
   func1(point);             // Передача копии. Вызывается 
                             // конструктор копирования!!!
   func2(&point);            // Передача указателя. Можно изменить
                             // значение исходного объекта
   point.dump();             // 4 12
   Point point2(0, 0);       // Объявление объекта
   point2 = func3(point);    // Механизм ссылок. Можно изменить
                             // значение исходного объекта
   point2.dump();            // 14 32
   return 0;
}

Если при объявлении параметра дополнительно указать ключевое слово const, то внутри функции доступа к обычным методам объекта не будет. Например, создадим функцию func4() внутри которой вызовем метод dump() (см. листинг 13.22):

void func4(const Point &p) {
   std::cout << p.x << " " << p.y << std::endl;
   p.dump();
}

Попробуем вызвать функцию:

func4(point);

В результате получим следующую ошибку при компиляции:

error: passing 'const Point' as 'this' argument discards qualifiers

Чтобы можно было вызвать метод dump() внутри функции func4(), следует его сделать константным:

void dump() const { std::cout << x << " " << y << std::endl; }

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов