В C++,Каково значение возврата по ссылке?
function() = 10;
работает, если функция возвращает переменную по ссылке.
Каковы его варианты использования?
В C++,Каково значение возврата по ссылке?
function() = 10;
работает, если функция возвращает переменную по ссылке.
Каковы его варианты использования?
Самый распространенный случай - реализовать такие вещи, как operator [].
struct A {
int data[10];
int & operator[](int i) {
return data[i];
}
};
Другой способ вернуть большой объект из класса с помощью функции accesor:
struct b {
SomeBigThing big;
const SomeBigThing & MyBig() const {
return big;
}
};
для того, чтобы избежать копирования накладных расходов.
В случае, если у вас есть класс, который содержит другую структуру, это может быть полезно непосредственно изменить содержащуюся структуру:
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;
}
Примечания: в этом примере было бы проще прямо публиковать m_s
, а не возвращать ссылку.
std::vector
имеет operator[]
, что не допускало бы vec[n] = m
.
Очень обычный случай использования, когда вы пишете массив, подобный классу. Здесь вы хотите перегружать operator []
так, как вы можете сделать a[0] = 10;
В этом случае вы бы хотели подпись быть как int& operator[](int index);
Геттеры/сеттеры например
class C
{
int some_param_;
public:
int& param() { return some_param_; }
int const& param() const { return some_param_; }
};
, но здесь вы должны пойти с some_param быть public int. Контейнеры предоставляют функции, возвращаемые по ссылке, например. vector<T>::operator[]
, чтобы вы могли написать v[k] = x
.
И эта реализация трудно реорганизовать, когда вам нужно удалить или заменить some_param_ объектом другого типа. – Basilevs
SO облажался мой ответ
Вам даже не нужно возвращать ссылку:
struct C { };
C f() {
return C();
}
int main() {
C a;
f() = a; // compiles fine
}
Поскольку такое поведение весьма удивительно, обычно следует возвращать константное значение или константный если у пользователя нет разумного намерения изменить результат.
Это может быть полезно при реализации аксессоров
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
Я не знаю, почему, но я ненавижу матрицы классов (и я численный аналитик) –
Рассмотрим следующий код, MyFunction возвращает указатель на межд и установить значение в междунар.
int *i;
i = MyFunction();
*i = 10;
Теперь укоротить, что
*(MyFunction()) = 10;
Он делает то же самое, что и первый кодовый блок.
Вы можете посмотреть ссылку как указатель, который всегда разыменовывается. Так что, если моя функция возвращала ссылка - не указатель - на междунар Фрист блок кода станет
int &i;
i = MyFunction();
i = 10;
и второй станет
MyFunction() = 10;
Это то, что я искал
Код, который вы отправили, не является законным C++ - ссылки должны быть инициализированы. – 2010-07-09 15:19:57
Другой классический случай:
class Foo {
Foo();
public:
static Foo& getSingleton();
};
вы также можете достичь метод цепочки (если такое желание) U петь возвращение по ссылке.
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);
}
named parameter 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
имеет конструктор, принимающий const CreateFoo&
.
Не обязательно, чтобы этот синтаксис работал. Вы всегда можете вернуть объект класса прокси, у которого есть 'operator =' выполнить назначение за кулисами –
, поэтому я никогда не обнимал C++ ... вы никогда не перестаете находить новые синтаксисы, которые полностью взорвут ваш разум. Обязательно перегрузите оператора: | –
Вы даже можете вернуть значение и назначить временное. Вот почему Скотт Мейерс рекомендует возвращать значение const. – Philipp