Подтвердить что ты не робот

Каково значение возврата по ссылке?

В С++,

function() = 10;

работает, если функция возвращает переменную по ссылке.

Каковы его варианты использования?

4b9b3361

Ответ 1

Самый распространенный случай - реализовать такие вещи, как operator [].

struct A {
    int data[10];
    int & operator[]( int i ) {
         return data[i];
    }
};

Другой - вернуть большой объект из класса через функцию accesor:

struct b {
    SomeBigThing big;
    const SomeBigThing & MyBig() const {
         return big;
    }
};

чтобы избежать накладных расходов на копирование.

Ответ 2

Рассмотрим следующий код: MyFunction возвращает указатель на int, и вы устанавливаете значение для int.

int  *i;
i = MyFunction();
*i = 10;

Теперь сократите это до

*(MyFunction()) = 10;

Он делает то же самое, что и первый блок кода.

Вы можете посмотреть ссылку как указатель, который всегда разыменовывается. Поэтому, если моя функция вернула ссылку, а не указатель на int, блок кода frist станет

int  &i;
i = MyFunction();
i = 10;

а вторая станет

MyFunction() = 10;

Это то, что я искал

Ответ 3

Getters/seters для примера

class C
{
    int some_param_;
public:
    int& param() { return some_param_; }
    int const& param() const { return some_param_; }
};

но здесь вы должны пойти с some_param, являющимся общедоступным int. Контейнеры предоставляют функции, возвращаемые по ссылке, например. vector<T>::operator[], чтобы вы могли написать v[k] = x.

Ответ 4

Очень обычный случай использования - когда вы пишете массив вроде класса. Здесь вы хотите перегрузить operator [] так, как вы можете сделать a[0] = 10; В этом случае вы хотели бы, чтобы подпись была как int& operator[](int index);

Ответ 5

Если у вас есть класс, который содержит другую структуру, может быть полезно непосредственно изменить содержащуюся структуру:

struct S
{
    int value;
};

class C
{
    public:

        S& ref() { return m_s; }

    private:

        S m_s;
};

Позволяет написать что-то вроде:

void foo()
{
    C c;

    // Now you can do that:

    c.ref().value = 1;
}

Примечание: в этом примере было бы проще прямо сделать public m_s публичным, а не возвращать ссылку.

Ответ 6

SO напортачил мой ответ

Вам даже не нужно возвращать ссылку:

struct C { };

C f() {
  return C();
}

int main() {
  C a;
  f() = a;  // compiles fine
}

Поскольку это поведение является довольно неожиданным, вы обычно должны возвращать значение const или ссылку на const, если у пользователя нет разумного намерения изменить результат.

Ответ 7

Это может быть полезно при реализации аксессуаров

class Matrix
{
   public:
      //I skip constructor, destructor etc

      int & operator ()(int row, int col)
      {
         return m_arr[row + col * size];
      }

   private:
      int size;
      int * m_arr;
}

Matrix m(10);
m(1,0) = 10;  //assign a value to row 1, col 0

Ответ 8

Другой классический случай:

class Foo {
  Foo();
public:
  static Foo& getSingleton();
};

Ответ 9

std::vector имеет operator[], который не разрешил бы vec[n] = m иначе.

Ответ 10

Вы также можете добиться цепочки методов (если хотите), используя возврат по ссылке.

class A
{
public:
    A& method1()
    {
        //do something
        return *this;   //return ref to the current object
    }
    A& method2(int i);
    A& method3(float f);  //other bodies omitted for brevity
};

int main()
{
    A aObj;
    aObj.method1().method2(5).method3(0.75);

    //or use it like this, if you prefer
    aObj.method1()
        .method2(5)
        .method3(0.75);
}

Ответ 11

Именованный параметр idiom - другой вариант использования. Рассмотрим

class Foo
{
public:
    Foo(
        int lions,
        float tigers,
        double bears,
        std::string zookeeper
    );
};

пользователям этого класса необходимо запомнить положение каждого параметра

Foo foo( 1, 2.0, 5, "Fred" );

что может быть неочевидным, не глядя на заголовок. По сравнению с таким типом создателя

class CreateFoo
{
friend class Foo;
public:
    CreateFoo();

    CreateFoo& lions(int lions) {
        _lions = lions;
         return *this;
    }

    CreateFoo& tigers(float tigers) {
        _tigers = tigers;
        return *this;
    }

    CreateFoo& bears(double bears) {
        _bears = bears;
        return *this;
    }

    CreateFoo& zookeeper(const std::string& zookeeper) {
        _zookeeper = zookeeper;
        return *this;
    }

private:
    int _lions;
    float _tigers;
    double _bears;
    std::string _zookeeper;
};

который затем может использоваться такими клиентами

Foo foo = CreateFoo().
    lions(1).
    tigers(2.0).
    zookeeper("Fred").
    bears(5)
    ;

Предполагая, что Foo имеет конструктор, принимающий a const CreateFoo&.