@Ptax

Почему программисты не любят возврат константных ссылок в C++?

Просматривая чужой код, обратил внимание на то, что почти никто при написании геттеров не использует возврат константной ссылки на приватный член класса. Что самое странное, это касается не только проектов с длинной историей, но и относительно свежих работ. Ведь, по идее, возврат ссылки значительно менее ресурсозатратная операция, особенно если речь идет не о тривиальных объектах, а о более-менее сложных структурах.
Как вы считаете, насколько хорош нижеследующий код? Если вы считаете, что он плох, пожалуйста напишите почему. Возможно в таком подходе есть невидимые для меня "подводные камни"? Спасибо.

#include <string>
#include <iostream>

class Foo{
public:
    Foo(const char* str)
        : m_value(str)
    {
    }

    const std::string& value() const{
        return m_value;
    }
private:
    std::string m_value;
};

int main(int argc, char** argv)
{
    if(argc < 1)
        return -1;

    Foo foo(argv[0]);

    auto&& bar = foo.value();
    std::cout << bar << std::endl;
    /* ... */

    return 0;
}
  • Вопрос задан
  • 2375 просмотров
Пригласить эксперта
Ответы на вопрос 8
Если предоставляется доступ к ресурсам текущего объекта, то возвращаемое значение -- ссылка (константность зависит, конечно, от того, запрещаем ли мы изменять эти данные). Иначе -- значение.
А теперь представим, что есть виртуальный класс Window с методом title. Как подклассы Window будут хранить title -- деталь реализации, но в getter они по контракту обязаны привести его к std::string. Отсюда и возврат по значению: в каком типе хранится значение -- деталь реализации.
Ответ написан
Комментировать
Rou1997
@Rou1997
Как вы считаете, насколько хорош нижеследующий код? Если вы считаете, что он плох, пожалуйста напишите почему.

Он не лаконичен, это минус, а какие плюсы? Если вы работаете с Qt, то такие конструкции в ваших классах действительно нужны, потому что многие методы классов Qt принимают именно такие параметры.
Ответ написан
AtomKrieg
@AtomKrieg
Давай я поищу в Google за тебя
После уничтожения объекта ссылка не валидна и не важно какая ссылка - константная или нет. В общем случае возврат ссылки рекомендован только на статик мембер класса. С сырым указателем такая же ситуация.
Используйте weak_ptr (перед каждым использованием надо проверять на expired) или shared_ptr для возврата из функций.
Ответ написан
Adamos
@Adamos
На самом деле, в жизни все может оказаться несколько сложнее. Если вы передаете по ссылке член класса, который сам является классом и содержит, например, контейнеры - то передача по ссылке не запустит конструктор копирования. Время это сэкономит, но создаст зависимость дальнейшей жизни кода от того, что там происходит внутри класса. То есть потенциальные грабли, от которых потом замучишься избавляться.
А программирование, как известно - это в первую очередь управление сложностью. Оптимизации стоят намного ниже в списке.
Ответ написан
@Mercury13
Программист на «си с крестами» и не только
Я думаю, причина единственная — не надо смотреть на время жизни объекта.
Если же нужно сэкономить, в возвращаемый результат встраивают умный указатель. Так работают, например, QString и QDatabase.

А вот в каких-нибудь низкоуровневых векторах — вполне себе константные ссылки.
const T &QVector::at(int i) const
Ответ написан
Комментировать
maaGames
@maaGames
Погроммирую программы
Всегда возвращаю константную ссылку для не встроенных типов, если это возможно в текущем контексте.
Ответ написан
Комментировать
vt4a2h
@vt4a2h Куратор тега C++
Senior software engineer (C++/Qt/boost)
Что касается кода... Код как код. Если есть реальная потребность возвращать по конст ссылке и без этого не обойтись, так возвращайте. Разумеется, если это не противоречит стандартам кодинга в вашей компании, структуре API и всему такому. В любом случае вы должны просчитать все последствия и варианты использования в реальном приложении. На синтетическом примере этого не увидеть. Я бы если честно предпочел видеть умные указатели, если приложение уж не совсем такое, где надо на всём экономить (а уж чтобы не использовать умные указатели, нужны обоснования и веские).
Если пользовательский тип поддерживает implicit sharing (можете прочитать про это в доках Qt, у них даже есть специальные классы, которые облегчают жизнь тем, кто хочет создавать свои "copy on write" классы), то его смело можно возвращать по значению. Это же справедливо и для smart pointer'ов.
Ответ написан
Комментировать
Daniro_San
@Daniro_San
Программист
Дело в том что если вы вернете константную ссылку на поле - само поле от этого не станет константным. А всё это очень хорошо приводится к обычному указателю, после чего можно менять значение поля.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы