0

この質問をするために、コードの一部を単純化する必要がありました。ただし、以下のコードでは、参照型として宣言していないという事実はx、関数が終了するとデクリメントの変更が「忘れられる」ことを意味しますか?

これを修正する最も賢明な方法は、 ?xとして宣言することです。AnotherClass& x

void MyClass::myFunc(unordered_map<int, AnotherClass>* dictionary, int z, int y){

    AnotherClass x = dictionary->at(z);

    //Does this change on x get "forgotten" in terms of what dictionary stores
    //once myFunc() has finished, because x is not a reference/pointer type?
    x.changeSomething(y--);
}


class MyClass{
    public:

    private:
        myFunc(unordered_map<int, AnotherClass>* dictionary, int z);
        unordered_map<int, AnotherClass>* dictionary

};
4

2 に答える 2

3

正しい。xの要素のコピーですdictionary。関数に対してローカルなコピーに変更を適用しています。呼び出し元側には何の影響も見られないはずです。参照を取得するか、 への呼び出しの結果に直接作用することができますat:

dictionary->at(z).changeSomething(z--);

これは、関数内にあるコードとは関係がないことに注意してください。

于 2013-10-27T15:18:17.207 に答える
2

Java や C# などの言語では、実際には、参照よりもメモリ内の同じオブジェクトを参照Thing t = s;するエイリアスを作成しています。ただし、C++ では、値とエイリアスは厳密に分離されています。ts

  • Thing t = s;のコピーを作成することについてですs
  • Thing& t = s;s(参照)と同じオブジェクトを参照するエイリアスを作成することについてです
  • Thing* t = &s;s(ポインター)と同じオブジェクトを参照するエイリアスを作成することについてです

参照とポインタの違いはここでは問題ではありません。重要なのは、コピーとエイリアスの違いです。

  • コピーへの変更は、そのコピーに対してローカルです
  • エイリアスによるオブジェクトへの変更は、そのオブジェクトに対してローカルであり、そのオブジェクトを参照するすべてのエイリアスを通じて表示されます

あなたの例に関しては:

// Fix 1: take dictionary by *reference* and not by *pointer*.
void MyClass::myFunc(std::unordered_map<int, AnotherClass>& dictionary, int z, int y){
    // Fix 2: dictionary.at(z) returns a "AnotherClass&"
    // that is an alias to the element held within the dictionary.
    // Make sure not to accidentally make a copy by using that "&"
    // for the type of x.
    AnotherClass& x = dictionary.at(z);

    // "x" is now a mere alias, the following call is thus applied
    // to the value associated to "z" within "dictionary".
    x.changeSomething(y--);
}

dictionary.at(z).changeSomething(y--);この場合、次のように記述できることに注意してください。ただし、いくつかの欠点があります。

  • が複数回再利用される場合xは、名前を付けることで明確になります。
  • 呼び出された関数/メソッドに副作用がある場合、呼び出しの数は重要であり、制御する必要があります。
  • パフォーマンスの観点からは、不必要に同じことを何度も計算するのを避けることは常に歓迎されます...しかし、パフォーマンスにこだわりすぎないでください;)
于 2013-10-27T16:08:20.403 に答える