14

注:両方の例を見たので、このPythonとC ++にタグを付けていますが、質問は言語に依存しません。

オブジェクトを変更する関数またはクラスメソッドには、2つの選択肢があります。問題のオブジェクトのデータを直接変更するか、新しいコピーを作成して、元のデータをそのままにして返すかです。一般に、関数から何が返されるかを見れば、どれがどれであるかがわかります。

場合によっては、両方を実行し、元のオブジェクトを変更してから、そのオブジェクトへのコピーまたは参照を返す関数が見つかります。これがどちらか一方だけを行うよりも有利な場合はありますか?

オブジェクトへの参照を返すことに依存するFluentInterfaceまたはMethodChainingの例を見てきましたが、それは文脈上明らかなはずの特殊なケースのようです。

私の最初の悪い例は、 Pythonのドキュメントから直接引用したもので、可変のデフォルトパラメータの問題を示しています。私にとって、この例は非現実的です。関数がパラメーターを変更する場合、デフォルトを設定しても意味がありません。コピーを返す場合は、変更を行う前にコピーを作成する必要があります。問題は、両方を実行しようとするためにのみ存在します。

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

2番目の例は、関数内のMicrosoftC++からのCStringT::MakeUpperものです。ドキュメントには、戻り値について次のように記載されています。

文字列のコピーを返しますが、すべて大文字で返します。

これにより、オリジナルは変更されないままであると予想されます。問題の一部は、ドキュメントが誤解を招くことです。プロトタイプを見ると、文字列への参照が返されていることがわかります。よく見ていない限り、これに気付くことはありません。結果を新しい文字列に割り当てると、エラーなしでコンパイルされます。驚きは後で来る。

4

2 に答える 2

4

C++の例Inc/Dec演算子

// 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;}
于 2012-10-10T00:08:41.683 に答える
2

オブジェクトを変更して参照を返したい C++ の明白な例がいくつかあります。

  1. 割り当て:

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

    これは、オブジェクト自体と引数の両方を変更し、それ自体への参照を返します。このように書くことができますa = b = c;

  2. IOストリーム:

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

    繰り返しますが、これにより操作の連鎖std::cout << t1 << t2 << t3;、または典型的な「抽出とチェック」が可能になりますif (std::cin >> n) { /* ... */ }

基本的に、入力オブジェクトの 1 つへの参照を返すことは、常に呼び出しをチェーンするか、結果の状態を何らかの形で評価するのに役立ちます。これには、いくつかの有用なシナリオがあります。

一方、引数を変更してからオブジェクトのコピーを返すことはあまり役に立たないようです。

于 2012-10-09T23:16:49.753 に答える