Рубрики

Когда мы передаем аргументы по ссылке или по указателю?

В C ++ переменные передаются по ссылке по следующим причинам:

1) Чтобы изменить локальные переменные функции вызывающей стороны: ссылка (или указатель) позволяет вызываемой функции изменять локальную переменную функции вызывающей стороны. Например, рассмотрим следующий пример программы, в которой fun () может изменять локальную переменную x функции main () .

void fun(int &x) {

    x = 20;

}

  

int main() {

    int x = 10;

    fun(x);

    cout<<"New value of x is "<<x;

    return 0;

}

Выход:
Новое значение х 20


2) Для передачи аргументов большого размера:
если аргумент большой, передача по ссылке (или указателю) более эффективна, потому что в действительности передается только адрес, а не весь объект. Например, давайте рассмотрим следующий класс Employee и функцию printEmpDetails (), которая печатает сведения о сотруднике.

class Employee {

private:

    string name;

    string desig;

  

    // Дополнительные атрибуты и операции

};

  

void printEmpDetails(Employee emp) {

     cout<<emp.getName();

     cout<<emp.getDesig();

  

    // Распечатать больше атрибутов

}

Проблема с приведенным выше кодом заключается в следующем: каждый раз, когда вызывается printEmpDetails () , создается новый объект Employee, который включает в себя создание копии всех элементов данных. Поэтому лучшей реализацией было бы передать Employee в качестве ссылки.

void printEmpDetails(const Employee &emp) {

     cout<<emp.getName();

     cout<<emp.getDesig();

  

    // Распечатать больше атрибутов

}

Этот пункт действителен только для переменных структуры и класса, поскольку мы не получаем никакого преимущества в эффективности для базовых типов, таких как int, char и т. Д.


3) Чтобы избежать нарезки объектов:
если мы передадим объект подкласса функции, которая ожидает объект суперкласса, то переданный объект будет разрезан, если он передан по значению. Например, рассмотрим следующую программу, в которой напечатано «Это домашнее животное».

#include <iostream>
#include<string>

  

using namespace std;

  

class Pet {

public:

    virtual string getDescription() const {

        return "This is Pet class";

    }

};

  

class Dog : public Pet {

public:

    virtual string getDescription() const {

        return "This is Dog class";

    }

};

  

void describe(Pet p) { // Нарезает производный объект класса

    cout<<p.getDescription()<<endl;

}

  

int main() {

    Dog d;

    describe(d);

    return 0;

}

Выход:
Это питомец класса

Если в приведенной выше программе мы используем передачу по ссылке, то она правильно печатает «Это класс собаки». Смотрите следующую измененную программу.

#include <iostream>
#include<string>

  

using namespace std;

  

class Pet {

public:

    virtual string getDescription() const {

        return "This is Pet class";

    }

};

  

class Dog : public Pet {

public:

    virtual string getDescription() const {

        return "This is Dog class";

    }

};

  

void describe(const Pet &p) { // Не разрезает производный объект класса.

    cout<<p.getDescription()<<endl;

}

  

int main() {

    Dog d;

    describe(d);

    return 0;

}

Выход:
Это класс собак

Этот пункт также недопустим для базовых типов данных, таких как int, char и т. Д.


4) Для достижения полиморфизма времени выполнения в функции

Мы можем сделать функцию полиморфной, передавая объекты как ссылку (или указатель) на нее. Например, в следующей программе print () получает ссылку на объект базового класса. print () вызывает функцию базового класса show (), если передается объект базового класса, и функцию производного класса show (), если передается объект производного класса.

#include<iostream>

using namespace std;

  

class base {

public:

    virtual void show() {  // Обратите внимание на виртуальное ключевое слово здесь

        cout<<"In base \n";

    }

};

  

  

class derived: public base {

public:

    void show() {

        cout<<"In derived \n";

    }

};

  
// Поскольку мы передаем b как ссылку, мы достигаем полиморфизма во время выполнения здесь.

void print(base &b) {

    b.show();

}

  

int main(void) {

    base b;

    derived d;

    print(b);

    print(d);

    return 0;

}

Выход:
В базе
В производном

Спасибо Venki за добавление этого пункта.

В качестве дополнительного примечания рекомендуется использовать константные аргументы-ссылки, если они передаются по ссылке только по причине no. 2 или 3, упомянутых выше. Рекомендуется избегать неожиданных изменений объектов.

Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Рекомендуемые посты:

Когда мы передаем аргументы по ссылке или по указателю?

0.00 (0%) 0 votes