Возврат ссылок из методов C ++ - PullRequest
4 голосов
/ 06 июля 2010

Дорогие друзья, меня беспокоит, что я неправильно использую ссылки в C ++ В следующем методе GCC выдает предупреждение «возвращена ссылка на локальную переменную« me »»

MatrizEsparsa& MatrizEsparsa::operator+(MatrizEsparsa& outra){
  MatrizEsparsa me(outra.linhas(),outra.colunas());
  return me;
}

Но при следующих изменениях предупреждение исчезает:

MatrizEsparsa& MatrizEsparsa::operator+(MatrizEsparsa& outra){
  MatrizEsparsa me(outra.linhas(),outra.colunas());
  MatrizEsparsa &ref = me;
  return ref;
}

Является ли прежний метод (возвращающий переменную 'ref') правильным \ приемлемым?

Ответы [ 5 ]

13 голосов
/ 06 июля 2010

Нет.ref по-прежнему относится к me, который будет уничтожен в конце вызова.

Вы должны вернуть копию своего результата (без префикса &).

MatrizEsparsa MatrizEsparsa::operator+(const MatrizEsparsa& outra) const {
    return MatrizEsparsa(outra.linhas(),outra.colunas());
}

Я также добавил два спецификатора const (к параметру и методу), поскольку я сомневаюсь, что outra или вызывающий экземпляр необходимо изменить в этом случае.(Я могу ошибаться, но тогда ваш operator+ будет иметь странную семантику)

Делая то, что вы сделали, вы просто сделали код более сложным.Компилятор, вероятно, был сбит с толку и не мог предупредить вас о вашей возможной ошибке.

Обычно, когда вам приходится использовать хитрые трюки, чтобы делать простые вещи, это означает, что что-то не так.

4 голосов
/ 06 июля 2010

Я думаю, вы ошибаетесь в своих операторах.

Есть 2:

struct Foo
{
  Foo& operator+=(Foo const&);
  Foo operator+(Foo const&) const;
};

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

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

Foo operator+(Foo const&, Foo const&);

Это может быть автоматизировано, поскольку это громоздко, используя Boost.Operators:

struct Foo: boost::addable<Foo>
{
  Foo& operator+=(Foo const& rhs)
  {
    // add
    return *this;
  }
};

Маленькая магия boost::addable автоматически сгенерирует реализацию + на основе Foo::operator+=.

2 голосов
/ 06 июля 2010

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

2 голосов
/ 06 июля 2010

Нет, здесь вы должны вернуть значение, в идеале - значение const.См. Эффективный C ++, пункт 21.

Я предлагаю следующий интерфейс:

const MatrizEsparsa operator+(const MatrizEsparsa& left, const MatrizEsparsa& right);

Обратите внимание, что все является либо ссылкой const, либо значением const.Возвращать значение const не так важно, как возвращать значение или объявлять параметры, как ссылки const, но аргументы Скотта Мейерса убедили меня, хотя никто не следует им.

0 голосов
/ 06 июля 2010

Вы не можете вернуть ссылку, так как объект, на который вы ссылаетесь, будет уничтожен вне вашего контроля. Либо поместите «я» в качестве переменной-члена MatrizEsparsa, чтобы оно сохранялось после выполнения функции, либо верните указатель или значение smart_ptr, указывающее на объект.

Хотя это оператор +, вы, вероятно, захотите вернуть значение, а не ссылку на внутреннюю переменную функции.

...