2

Visual C ++で作成したプログラムで次の問題が発生しました。誰かが私を助けてくれることを願っています:

typedef struct spielfeld
{
 int ** Matrix;
 int height; 
 int width; 
 Walker walker;
 Verlauf history;
} Spielfeld;

void show(Spielfeld fieldToShow); //Prototype of the Function where I have this
                                  //problem

int main(int argc, char *argv[])
{
  int eingabe;
  Spielfeld field;

  //Initialize .. and so on

  //Call show-Function and pass the structure with Call by Value
  show(field);
  //But what's happened? field.Matrix has changed!!
  //can anyone tell me why? I don't want it to become changed!
  //cause that's the reason why I pass the field as Call by Value!
}

void show(Spielfeld fieldToShow)
{
 //Here is the problem: Alltough the parameter fieldToShow has been passed
 //with call by value, "fieldToShow.Matrix[0][0] = 1" changes the field in 
 //main!!
 fieldToShow.Matrix[0][0] = 1;

 //Another try: fieldToShow.walker.letter only affects the local fieldToShow, 
 //not that field in main! That's strange for me! Please help!
 fieldToShow.walker.letter  = 'v';
}
4

5 に答える 5

9

構造体を渡すときは、値で渡します。ただし、その中のマトリックスは、intへのポインターへのポインターとして実装されます。これらのポインターは参照であるため、関数でそれらによって参照される値を変更すると、同じ値がの元の構造によって参照されmainます。

これらのオブジェクトを値で渡したい場合は、自分でディープコピーを実行する必要があります。このコピーでは、新しいマトリックスを割り当て、すべての値を元のマトリックスからそのマトリックスにコピーします。

Drewが指摘しているように、C ++では、そのディープコピーを実装するための推奨される方法は、コピーコンストラクターを使用することです。コピーコンストラクターを使用すると、オブジェクトを明示的にコピーしなくても、オブジェクトが値によって渡されるたびにディープコピーを実行できます。

クラスとコンストラクターの準備がまだできていない場合は、Spielfeld copySpielfeld(Spielfeld original)そのディープコピーを実行する関数(おそらく)を作成するだけです。Spielfeldこれは、新しいを作成する代わりに、渡された値を取得することを除いて、例で省略した初期化コードと基本的に同じですSpielfeld。APIをどのように機能させるかに応じてfieldshow関数に渡す前にこれを呼び出すか、渡された引数に対して関数に実行させることができます。show

于 2010-01-08T17:45:56.967 に答える
3

を渡すときにポインタをコピーしていますfieldToShow。値渡しはディープコピーを実行しないため、Spielfeldの呼び出しshow(...)main(...)(別個ではありますが)の両方がMatrixに対して同じ値を持ちます。

これを修正するのは簡単ではありません。おそらく最も簡単な方法は、(基本的にshow(...)使用して)参照渡しに変更し、関数の開始時に明示的なコピーを作成することです。Spielfeld*

于 2010-01-08T17:41:44.820 に答える
2

Spielfeldオブジェクトがコピーされたとき:

  • コピーには、オリジナルの「ウォーカー」のコピーである独自の「ウォーカー」があります。ウォーカーは構造体であるため、2つの構造体があることを意味します。
  • コピーには、オリジナルの「Matrix」メンバーのコピーである独自の「Matrix」メンバーがあります。ただし、Matrixはポインターです。つまり、2つのポインターがあります。ポインタのコピーは、元のポインタが指しているものと同じものを指します。

したがって、コピーのウォーカーの内容を変更しても、ウォーカーが異なるため、オリジナルには影響しません。コピーのマトリックスの内容を変更すると、同じマトリックスを共有するため、元のマトリックスに影響します。

于 2010-01-08T17:44:18.407 に答える
1

構造体は値によって渡され始めますが、ポインター(マトリックス)が含まれているため、そのポインターが指しているものは、構造体にアクセスできる人なら誰でも変更できます。これを望まない場合は、ポインタをconstにすることができます。

于 2010-01-08T17:41:33.120 に答える
0

興味深い雑学として:これは、Javaで値による呼び出しがどのように機能するかです。オブジェクト参照は常に値によって渡されます。これらの参照が難しいオブジェクトを操作すると、参照による呼び出しが発生したように感じられます。

あなたの質問とは本当に何の関係もありませんが、おそらくあなたはその興味をそそられるでしょう。

ハッピーハッキング

于 2010-01-08T18:30:47.220 に答える