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

Имеет ли смысл изменять место и возвращать копию?

Примечание. Я помещаю этот Python и С++, потому что я видел примеры в обоих, но вопрос является языковым агностиком.

Метод или метод класса, который модифицирует объект, имеет два варианта: изменить данные непосредственно в рассматриваемом объекте или создать новую копию и вернуть ее, оставив исходный нетронутый. Как правило, вы можете определить, что есть, посмотрев на то, что вернулось из функции.

Иногда вы найдете функцию, которая пытается сделать то же самое, изменить исходный объект, а затем вернуть копию или ссылку на этот объект. Есть ли когда-нибудь случай, когда это дает какое-либо преимущество перед тем, как делать только одно или другое?

Я видел пример Fluent Interface или Цепочка метода, который основан на возврате ссылки на объект, но это похоже на частный случай, который должен быть очевиден в контексте.

Мой первый плохой пример приведен прямо из документации Python и иллюстрирует проблему изменчивых параметров по умолчанию. Для меня этот пример нереалистичен: если функция изменяет свой параметр, то нет смысла иметь по умолчанию, и если он вернет копию, то копия должна быть сделана до того, как будут сделаны какие-либо изменения. Проблема существует только потому, что она пытается сделать оба.

def f(a, L=[]):
    L.append(a)
    return L

Второй пример - Microsoft С++ в CStringT::MakeUpper. В документации говорится об возвращаемом значении:

Возвращает копию строки, но все символы верхнего регистра.

Это приводит к тому, что оригинал остается неизменным. Часть проблемы заключается в том, что документация вводит в заблуждение, если вы посмотрите на прототип, вы обнаружите, что он возвращает ссылку на строку. Вы не заметите этого, если не присмотритесь и присвоите результат новой компиляции строк без ошибок. Удивление приходит позже.

4b9b3361

Ответ 1

С++ Пример Inc/Dec operator

// Pre-Increment: Create a new object for return and modify self.
myiterator  operator++(int) {myiterator tmp(*this); operator++(); return tmp;}


// Post-Increment: modify self and return a reference
myiterator&  operator++() {/* Do Stuff*/ return *this;}

Ответ 2

В С++ есть некоторые очевидные примеры, где вы хотите изменить объект и вернуть ссылку:

  • Назначение:

    T & T::operator=(T && rhs)
    {
        ptr = rhs.ptr;
        rhs.ptr = nullptr;
        return *this;
    }
    

    Этот параметр изменяет как сам объект, так и аргумент, и возвращает ссылку на себя. Таким образом вы можете написать a = b = c;.

  • IOStreams:

    std::ostream & operator<<(std::ostream & os, T const & t)
    {
        os << t->ptr;
        return os;
    }
    

    Опять же, это позволяет цепочки операций, std::cout << t1 << t2 << t3; или типичный "извлечение и проверка" if (std::cin >> n) { /* ... */ }.

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

С другой стороны, изменение аргумента, а затем возвращение копии объекта оказывается менее полезным.