Skip to content

Commit ecae7df

Browse files
authored
Merge pull request #1033 from shiracamus/update-pass-by-value.md
Revise pass-by-value and pass-by-reference documentation
2 parents 58551ab + 26c3892 commit ecae7df

File tree

1 file changed

+58
-26
lines changed

1 file changed

+58
-26
lines changed

docs/reference/functions/pass-by-value.md

Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,74 @@
11
# 値渡しと参照渡し
22

3-
プログラミング言語によっては、引数の渡し方に値渡し(pass-by-value)と参照渡し(pass-by-reference)の2種類が存在するものがあります。
3+
関数の実引数に変数を指定するとき、仮引数への渡し方に値渡し(pass-by-value)と参照渡し(pass-by-reference)の 2 種類があります(値渡しは更に細かく分けられます)。
4+
5+
- 実引数:関数を呼び出す側が引き渡す即値(123 など)か変数
6+
- 仮引数:関数側が引き受ける変数
7+
8+
参照渡しできないプログラミング言語もあります。
9+
10+
- 参照渡しできる言語:C++, C#, VB.NET, PHP, Swift など
11+
- 参照渡しできない言語:C, Java, JavaScript, Python, Ruby など
12+
13+
## 変数の種類
14+
15+
変数には値型と参照型の 2 種類があります。
16+
17+
- 値型変数:変数に代入値が保持される(保持値=代入値)
18+
- 参照型変数:変数に参照値が保持され、変数から代入値を参照する(保持値 ≠ 代入値)
19+
20+
参照値は、代入値がメモリ上のどこにあるのかを識別する値で、メモリアドレスなどが用いられます。
21+
値型変数も参照型変数も値渡しと参照渡しができます。
422

523
## 値渡し
624

7-
値渡しは、変数が関数に渡るタイミングで、変数が別の変数にコピーされます。元々同じ変数でも、関数の呼び出し元と関数の内部処理では、独立した値になります。そのため、関数の処理で引数に値を代入しても、関数呼び出し元の変数に影響しません。次は、C言語の値渡しの例です。変数`a``1`で初期化され、関数`change``a`が渡されます。`change`では引数に`2`を代入しますが、呼び出し元の変数`a``1`のままです。
25+
値渡しは、変数の値(保持値)が渡されます。
26+
27+
- 値型変数:代入値のコピーが渡される(コピー渡し)
28+
- 参照型変数:参照値のコピーが渡され、参照先の値はコピーされずに共有される(参照の値渡し、共有渡し、値共有)
29+
30+
実引数と仮引数は、独立した変数、独立した値になります。そのため、関数内で仮引数に値を代入しても、関数呼び出し元に影響しません。
31+
次のコードは、C++言語の値渡しの例です。変数`a``1`で初期化され、関数`change`に変数`a`の値が渡されます。関数`change`内で仮引数`n``2`を代入しても、呼び出し元の変数`a``1`のままです。
832

9-
```c
10-
#include <stdio.h>
33+
```cpp
34+
#include <print>
1135

12-
void change(int n) {
13-
n = 2;
36+
void change(int n) { // 仮引数nは値型変数の値渡し
37+
n = 2; // 仮引数に代入しても呼出し元に影響しない
1438
}
1539

1640
int main() {
17-
int a = 1;
18-
change(a);
19-
printf("%d", a); //=> 1
41+
int a = 1; // 値型変数
42+
change(a); // 実引数は値型変数a
43+
std::println("{}", a); //=> 1
44+
return 0;
2045
}
2146
```
2247
2348
## 参照渡し
2449
25-
参照渡しは、関数呼び出し元の変数が関数の処理でも共有されます。もし、関数の処理で引数に値を代入すると、関数呼び出し元の変数も変化します。次のコードはC言語の参照渡しの例です。変数`a`は関数`change`に参照渡しされます。`change`は引数に`2`を代入すると、`change`の呼び出し元の変数`a`の値も`2`になります。
50+
参照渡しは、変数自体が渡されます。呼び出し元の変数を参照するようにして変数が共有されます(変数共有)。
51+
実引数と仮引数は、同じ変数、同じ値になります。そのため、関数内で仮引数に値を代入すると、関数呼び出し元に影響します。
52+
次のコードは、C++言語の参照渡しの例です。 変数`a`は`1`で初期化され、関数`change`に変数`a`自体が渡されます(呼び出し元の変数を参照・共有します)。関数`change`内で引数に`2`を代入すると、呼び出し元の変数`a`の値も`2`になります。
2653
27-
```c
28-
#include <stdio.h>
54+
```cpp
55+
#include <print>
2956
30-
void change(int *n) {
31-
*n = 2;
57+
void change(int &n) { // 仮引数nは値型変数の参照渡し
58+
n = 2; // 仮引数に代入すると呼出し元に影響する
3259
}
3360
3461
int main() {
35-
int a = 1;
36-
change(&a);
37-
printf("%d", a); //=> 2
62+
int a = 1; // 値型変数
63+
change(a); // 実引数は値型変数a
64+
std::println("{}", a); //=> 2
65+
return 0;
3866
}
3967
```
4068

41-
## JavaScriptは値渡し
69+
## JavaScript は値渡し
4270

43-
JavaScriptではこのような参照渡しをする機能はありません。関数の引数はすべて値渡しになります。したがって、引数に値を代入する処理を関数に書いても、その影響は関数呼び出し元には影響しません
71+
JavaScript には C++のような参照渡しをする機能はありません。関数の引数はすべて値渡しです。したがって、仮引数に値を代入しても関数呼び出し元には影響しません
4472

4573
```js twoslash
4674
function change(n) {
@@ -52,7 +80,9 @@ console.log(n);
5280
// @log: 1
5381
```
5482

55-
ところが、オブジェクトについては少し特殊です。オブジェクトはどこでも参照になります。どういうことかというと、オブジェクトに別の変数名をつけても、オブジェクトが複製されて新たなオブジェクトができるのではなく、異なる変数名同士でひとつのオブジェクトを指すということです。たとえば、次の例のようにオブジェクト`{ n: 1 }`を変数`x`に代入し、さらに`x`を変数`y`に代入すると、`x``y`は同じオブジェクトを参照します。もし、`y`のプロパティ`n`を変更すると、`x``n`も変化します。
83+
ところが、オブジェクトについては少し特殊です。オブジェクトは参照型で変数はオブジェクトを参照します。
84+
その変数を別の変数に代入したとき、オブジェクトがコピーされて新たなオブジェクトが作られるのではなく、異なる変数から同じオブジェクトを参照します。
85+
たとえば、次のコードのようにオブジェクト`{ n: 1 }`を変数`x`に代入し、さらに変数`x`を変数`y`に代入すると、変数`x`と変数`y`は同じオブジェクトを参照します。変数`y`のプロパティ`n`を変更すると、変数`x`のプロパティ`n`も変更されます。
5686

5787
```js twoslash
5888
const x = { n: 1 };
@@ -62,7 +92,7 @@ console.log(x);
6292
// @log: { n: 2 }
6393
```
6494

65-
ただし、`y`に別の値を代入した場合は、`x``y`は共通のオブジェクトを参照しなくなり、`y`への変更は`x`には影響しなくなります。
95+
ただし、変数`y`に別の値を代入した場合は、変数`x`と変数`y`は同じオブジェクトを参照しなくなり、変数`y`のプロパティの変更は変数`x`には影響しなくなります。
6696

6797
```js twoslash
6898
const x = { n: 1 };
@@ -73,7 +103,9 @@ console.log(x);
73103
// @log: { n: 1 }
74104
```
75105

76-
以上のようにJavaScriptでは、あるオブジェクトに別の変数をつけたとき、そのオブジェクトを共有するようになっています。共有されたオブジェクトはプロパティを変更した場合、他の変数にもその変更が影響します。この仕様は引数にも同じことが言えます。たとえば、次の例です。オブジェクト`{ n: 1 }`を変数`x`に代入し、さらに`x`を関数`change`の引数`y`に代入すると、`x``y`は同じオブジェクトを参照します。`y`のプロパティを変更すると、その影響は関数呼び出し元の`x`のプロパティにも影響します。
106+
以上のように JavaScript では、オブジェクトが代入されてる変数を別の変数に代入したとき、参照先のオブジェクトを共有するようになっています。
107+
共有されたオブジェクトのプロパティを変更すると他の変数にも影響します。この仕様は関数の引数も同様です。
108+
たとえば、次のコードのようにオブジェクト`{ n: 1 }`を変数`x`に代入し、さらに変数`x`を関数`change`の引数`y`に渡すと、変数`x`と変数`y`は同じオブジェクトを参照します。変数`y`のプロパティを変更すると、その影響は関数呼び出し元の変数`x`のプロパティも変更されます。
77109

78110
```js twoslash
79111
function change(y) {
@@ -85,7 +117,7 @@ console.log(x);
85117
// @log: { n: 2 }
86118
```
87119

88-
引数の場合も、変数の再代入の仕様と同様に、`y`に別の値を代入した場合は、`x``y`は同じオブジェクトを参照しなくなるため、`y`への変更は`x`に影響しなくなります。
120+
引数の場合も、変数の再代入の仕様と同様に、変数`y`に別の値を代入した場合は、変数`x`と変数`y`は同じオブジェクトを参照しなくなるため、変数`y`への変更は変数`x`に影響しなくなります。
89121

90122
```js twoslash
91123
function change(y) {
@@ -98,12 +130,12 @@ console.log(x);
98130
// @log: { n: 1 }
99131
```
100132

101-
以上をまとめると、JavaScriptの関数の引数は値渡しです。注意点として、オブジェクトは変数の場合と同様に、引数と呼び出し元の変数は同じオブジェクトを共有する仕様です。そして、もし引数のオブジェクトのプロパティを変更した場合、その変更は関数呼び出し元に影響します。
133+
以上をまとめると、JavaScript の関数の引数は値渡しです。注意点として、オブジェクトは変数の場合と同様に、引数と呼び出し元の変数は同じオブジェクトを共有する仕様です。そして、もし引数のオブジェクトのプロパティを変更した場合、その変更は関数呼び出し元に影響します。
102134

103135
<PostILearned>
104136

105-
JavaScriptの引数は値渡し
106-
JavaScriptにはC言語の参照渡しと同等の仕組みはない
137+
JavaScript の引数はすべて値渡し
138+
JavaScript には C++言語の参照渡しと同等の仕組みはない
107139
・ただし、オブジェクトは値を共有する
108140
・共有したオブジェクトを関数で変更した場合、呼び出し元にも影響する
109141
・オブジェクトの共有は引数に限ったことではない

0 commit comments

Comments
 (0)