質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Q&A

解決済

3回答

1194閲覧

代入(assignment)は、浅いコピーですか?

momon-ga

総合スコア4826

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

1グッド

6クリップ

投稿2020/02/06 04:21

編集2020/02/14 05:21

たまに代入について浅いコピー(shallow copy)というのを見て違和感を覚えたのですが、
シャローコピーというのは言語により違いがあったり、定義は不明確なものなのでしょうか。

特に困ってるわけではないのですが、見るたびにモヤモヤするので、ハッキリできるなら解消したいと思っています。

(2020/02/14 追記)
回答、参照ありがとうございました。
いったんクローズいたしますが、何か意見などあれば回答していただけたらコメントいたしますので追加回答歓迎です。

■反省点
代入について固定概念(前提?)があって、そこを表現し忘れたのがあり。
単純に代入演算子だけでは、答えられないことに気づいたのですが、訂正すると既回答が無駄になってしまうので、そのままにしました。

javaでも

java

1Object obj1 = otherObj; 2Object obj2 = otherObj.clone();

で、挙動が違いますもんね・・・(代入を前者の使い方固定で考えてました)

pythonは、右辺が変数でも左辺の記述で挙動が違うのは面白い知見でした。(hayataka2049さん ありがとうございます)
(2020/02/14 ここまで)

■聞きたいこと
代入をシャローコピーというのか?
そのプログラミング言語は何か?
シャローコピーという根拠のようなものがあれば教えてもらいたい

■調べたこと
・wiki:https://en.wikipedia.org/wiki/Object_copying

浅いコピーと深いコピーの用語は、Smalltalk -80にまでさかのぼります。

・Smalltalk-80と思われる当該箇所

6 Protocol for all Objects
Copying Objects

イメージ説明

代入の場合、originalとshallow copyが同じものを指していると思われるため、コピーと違うのでは?と思っています。
当該箇所でも a==bは、falseとなっています。
イメージ説明

・掲示板
No, shallow copy is not the same as assignment in Smalltalk.

■その他
javaでの代入とシャローコピーの違いだと、私が考えているもののサンプルです。

java

1 public static void main(String[] args) { 2 3 System.out.println("代入"); 4 int[][] a = {{0,0,0}, {1,1,1}}; 5 int[][] ac = a; // 代入(assignment) 6 System.out.println("a == ac : " + (a == ac)); // コピー元、先は同じオブジェクト 7 ac[0][0] = 3; // 参照先を変更 8 System.out.println("a equal ac " + Arrays.equals(a, ac)); 9 ac[1] = new int[] {2}; // 参照先を変更 10 System.out.println("a equal ac " + Arrays.equals(a, ac)); 11 12 System.out.println(); 13 System.out.println("シャローコピー"); 14 15 a = new int[][] {{0,0,0}, {1,1,1}}; 16 int[][] aSc = new int[2][]; 17 System.arraycopy(a, 0, aSc, 0, 2); // 浅いコピー 18 System.out.println("a == aSc : " + (a == aSc)); // コピー元、先は異なるオブジェクト 19 20 aSc[0][0] = 4; // 参照先を変更 21 System.out.println("a equal aSc " + Arrays.equals(a, aSc)); // true 22 aSc[1] = new int[] {2}; // 参照先を変更 23 System.out.println("a equal aSc " + Arrays.equals(a, aSc)); // false 24 }
LouiS0616👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

(2020/02/13 全面修正)

変数への代入時にコピーが行われるかどうかは、その対象が「値」であるか「参照」であるかの違いに拠ります。

対象が値の場合、変数への代入時にはデータそのものがコピーされるため、まさにシャローコピーと呼ばれる挙動と同様の振る舞いとなります。
これを指して「代入はシャローコピーである」と表現するのは、表現の是非は別として、間違いではないと思います。

C# や C++ の言語では、値そのものを直接扱うことが可能なため、代入がシャローコピーとなる状況がしばしば発生します。

さらに、プログラミング言語によっては上記のルールに当てはまらない特殊な処理を行っているものもあり、例えば PHP の配列は、変数の内容は参照であるにも関わらず、値型のような振る舞いが期待されており、実際そのように振る舞うような暗黙的なコピー処理が実装されているとのことです。

「シャローコピー」とは、言い換えると「対象のクローン」に相当し、対象が持つ「値」をそっくりそのまま持った新たなデータを生成することを指します。
代入によって発生するのは値の複製以上のものではないため、代入時にデータの複製が発生する場合は、必ずシャローコピーとなります (特殊な処理を実装していない限り)。

結局のところ、これは一般的に振る舞いの異なる値型と参照型を区別せずに扱うことにより起きる混乱だと思います。
値型を扱わない、扱えない言語 (例えば Ruby のような、全てのデータが参照型と同じ振る舞いをするように作られた言語) においては、代入によってコピーが行われる状況は通常発生しないため、この場合は「代入はシャローコピーである」は明確に間違いになります。


以下は過去の回答です。

こんにちは。

質問者さんの考えの通り、一般的な表現においては、代入はシャローコピーではありません。
「コピー」は「オブジェクトの複製」を表しており、オブジェクトの複製を伴わない代入はコピーに該当しないからです。

ただし、プログラミング言語は星の数ほど存在するので、
代入時に本当にオブジェクトを複製してしまう「代入はシャローコピー」が成り立つようなプログラミング言語が存在するかもしれません。
用語を濫用し、代入をシャローコピーと呼ぶ低品質なリファレンスを持つプログラミング言語が存在するかもしれません。


以上の話は扱う対象が「オブジェクト」であることが前提です。
オブジェクトを雑に定義すると、「存在の同一性が確認可能なもの」とでもしておきます。
このとき、値はオブジェクトではない (全く同じ中身を持っていても、それが同じ存在であるかどうかは分からない) ため、代入とコピーの議論から外れます。

コメントで maisumakun さんからサジェストを頂きましたが、
C++ のオブジェクトは「値」としても扱うことができ、その場合は代入操作で自身が複製されるため、まるでシャローコピーされたような挙動になります。
PHP の配列は値である、とのことなので、オブジェクトとしてではなく値としての代入の振る舞いを再現しており、内部的には参照であるにもかかわらず、代入時に (※) コピーを行っています。

少なくとも、「オブジェクトの定義を満たすものの代入」について、上記言語においても本回答の内容は成り立っています。

投稿2020/02/06 04:35

編集2020/02/13 05:05
tamoto

総合スコア4252

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/02/06 04:40

> 代入時に本当にオブジェクトを複製してしまう「代入はシャローコピー」が成り立つようなプログラミング言語が存在するかもしれません。 C++のオブジェクト型は、あえて参照で扱わなければコピー(もしくは条件によってはムーブ)となります(コピーコンストラクタに手を入れて、自分なりの実装に変えたり、コピーを禁止したりもできます)。あと、PHPの配列も値型として、代入でコピーされるように振る舞います(実際にはCopy on Writeでコピーは遅延されます)。
tamoto

2020/02/06 04:49

なるほど。 C++ は書いたことがないのですが、 その動作はコピーというよりは、オブジェクト参照値の代入の代わりに値の代入をしているだけでどちらも同じものであるという考えなので、それを「コピーされる」と表現するのはあまりしっくりこないですね。 値として扱っているものを「オブジェクト」と呼ぶこと自体に抵抗があります。
hihijiji

2020/02/06 04:57

tamotoに同意します。 変数xを変数yに代入 → xとyは同じ参照を持つ 変数xを変数yにコピー → xとyは同じ参照値を持つ別の参照を持つ こんな感じでしょうか?
hihijiji

2020/02/06 05:08

質問者さんへですが、前提知識としてスタック領域とヒープ領域について理解が必要です。 OSや言語によらず必要な基礎知識ですからこの機会に学んでください。
momon-ga

2020/02/06 05:22

hihijijiさんへ > 質問者さんへですが、前提知識としてスタック領域とヒープ領域について理解が必要です。 この部分について、前提知識が必要なのか理由を教えていただけないでしょうか。 当方メモリ管理する言語を使っていないので、あえていうならヒープ領域ぐらいしかわからないです。 それと代入がシャローコピーとして実装されているのかなどの話と結びつきませんでした。 知識がないから関連性に気づかないものでしょうか。 プログラマなら知っておけいたほうがいい。というたぐいのものであれば了解しました。
hihijiji

2020/02/06 06:58

> プログラマなら知っておけいたほうがいい。というたぐいのもの その通りです。 というか質問自体がそのたぐいのものでしょう? 言語と使用条件を特定せず shallow copy を語る時点で概念の話になるので、教養以上の話にはなりえません。
Zuishin

2020/02/13 00:02 編集

C# でも構造体を別の変数に代入する際にコピーが行われます。その構造体が何らかの参照を保持していた場合、その参照先のオブジェクトはコピーされません。コピーされるのは参照だけです。私はこれをシャローコピーと呼んで差し支えないと思います。
Zuishin

2020/02/13 00:17

https://en.m.wikipedia.org/wiki/Object_copying ここの shallow copy の説明はまさに C# の構造体の代入を説明していました。 すなわちここの説明は、「代入をシャローコピーと呼んでいる」のではなく、「C# の構造体の代入のようにフィールドをコピーする代入をシャローコピーと呼んでいる」のではないでしょうか。 そしてディープコピーは、代入だけでなくそれぞれのフィールドの参照先もコピーしなければならないので、単なる代入とは違います。そこからこの質問者さんの誤解が生じていると考えられます。
Zuishin

2020/02/13 00:19

要するに参照を持つ C# の構造体の場合は、代入はシャローコピーであり、ディープコピーには一手間必要となります。 文脈を無視してこの文の一部を取り出すと、「代入はシャローコピーである」となります。
Zuishin

2020/02/13 00:22

C++ のクラスも基本は構造体であり、C# で言う値型なので、同じことが言えます。
tamoto

2020/02/13 00:29

構造体は確かにコード上ではシャローコピーに近しい挙動をしますが、この回答で提示した「オブジェクト」の定義には当てはまらないため、言及の対象から外しておりました。 実際にはボクシングによりオブジェクトに仕立てることはできますが、シンプルな定義に落とし込むためその点はあえて無視しています。 また、質問者さんは「ディープコピー」について一切言及していないため、「シャローコピー」と「共有 (コピーなし)」の2つの違いについてのみ解説しています。ディープコピーとシャローコピーの違いについては既に理解されているものと思っています。
Zuishin

2020/02/13 00:32

構造体のインスタンスはオブジェクトでしょう。「値はオブジェクトではない」は独自の定義であり、一般的な用語ではありません。
Zuishin

2020/02/13 00:34

またシャローコピーはディープコピーとの比較においてのみ定義できる言葉です。シャローについて言及しないのであれば、回答の方向性が間違っていると言わざるを得ません。
tamoto

2020/02/13 00:40

シャローコピーは、言い換えると「クローン」です。用語としてはディープの対比ではありますが、本質問においては実質的にクローンに関する質問だと読み取ったためこのような回答となりました。 質問者さんの反応がないので実際どうなのかは返答待ちですが。 「構造体のインスタンスはオブジェクトである」は厳密には正しくないと思います。構造体の性質として、オブジェクトに要求される性質を満たしません。C# においては、「構造体は常にオブジェクトに昇格可能」と考えるのがより正確だと考えています。いかがでしょうか。
maisumakun

2020/02/13 00:44

> 値として扱っているものを「オブジェクト」と呼ぶこと自体に抵抗があります。 > 「構造体のインスタンスはオブジェクトである」は厳密には正しくないと思います。 では、「オブジェクト」の厳密な定義とは何でしょうか。
Zuishin

2020/02/13 00:45

本質問の発端となった URL が質問に上げられています。それを読み、そこに書かれていることを把握してから回答してください。さもなくばズレた回答にしかなりません。 また構造体はオブジェクトに「昇格可能」ではなく、ボクシング無関係にオブジェクトです。
tamoto

2020/02/13 00:58

maisumakun さんへ 自分が「オブジェクト」と呼んでいるものは、 * プログラム内で一つの単位として扱えるデータの塊 * データの型により分類可能なもの * データの同一性が確認可能なもの を満たすものです。 このとき、単なる「値」は3つ目の条件を満たさないためオブジェクトと呼ぶことはしていません。 仮に、値をオブジェクトに含ませると、「オブジェクトを変数に代入」するような操作を行う際に、ものによってはコピーされ、ものによっては共有され、と動作に一貫性がなくなるため、これらを「同じ性質を満たすもの」と分類するのは矛盾があります。
maisumakun

2020/02/13 01:01

> ものによってはコピーされ、ものによっては共有され、と動作に一貫性がなくなるため その「一貫性のない」代入自体が、この議論の対象だと思っていたので、それを排除してしまうと議論の前提が崩壊すると考えます。
tamoto

2020/02/13 01:06

代入の一貫性のなさは、単なる「値」と「オブジェクト」の振る舞いの違いである、というのがこの回答の趣旨だったのですが、それに間違いがありましたでしょうか。
maisumakun

2020/02/13 01:09 編集

C++のオブジェクトは「データの同一性が確認可能なもの」としても実装可能ですが、代入でコピーされます。
Zuishin

2020/02/13 01:09

代入の一貫性のなさは参照型と値型の振る舞いの違いです。繰り返しているように、値型のオブジェクトもオブジェクトです。 そしてこの質問の焦点はそこにありません。値型の振る舞いであるフィールドコピーをシャローコピーと呼んでいいのかという質問です。
tamoto

2020/02/13 01:19

Zuishin さん なるほど。「値もオブジェクト」は暗黙変換を含んで object 型に統合できる話だと思っていますが、struct object と書いていますね。この記述が便宜的なものでないのなら、自分の発言が間違いでした。内容を再確認し、後ほど編集しようと思います。 ただ、その記事自体は、 Value と Object の対比を記述しているように見えるのが気になります。 maisumakun さん 同一性は、同じ対象を観測する二者がいる状況で、片方がデータに変更を加えた場合にもう片方からもその変更が観測可能であることを満たさないといけないため、代入でコピーされている時点でそれを満たせないのです。
Zuishin

2020/02/13 01:21

Object ID ですね。
maisumakun

2020/02/13 01:23

結局の所、状況が決まらない「シャローコピー」についての話題なので、tamotoさんが勝手に「オブジェクト」の範囲を切ってその中だけで議論するのでは、質問者の知りたいところまで含めてバッサリ切り捨ててしまう結果となる、という印象です。
tamoto

2020/02/13 01:25

その記事の見出しは正しくは「オブジェクトの同一性と値の同値性」ですね。 まさにこのコメントで話題にしていた内容です。
tamoto

2020/02/13 01:26

maisumakun さん おっしゃるとおりでした。その点も考慮の上、後ほど回答の方を修正いたします。
Zuishin

2020/02/13 01:28

C# では値型も参照型もオブジェクトですし、他の言語も含めた一般的な定義では、オブジェクトの実装について値であってはならないというものはありません。 現に C# でのクラスインスタンスは値であり、オブジェクトは主に値を指します。 そして C++ では参照型というものが無く、値であるインスタンスを必要に応じて値あるいは参照として変数に代入するものです。
Zuishin

2020/02/13 01:31

Value と Object の対比ではありません。値と参照の対比です。
tamoto

2020/02/13 01:39

Zuishin さん 自分が「オブジェクト」と呼んでいたものは C# の「値型もオブジェクト」のような便宜的なものでなく、Ruby 等の言語が主張する「全てはオブジェクトである」のオブジェクトを考えていました。 C++ ともなると、単なる struct をオブジェクトと呼ぶのですね。これは自分の認識が偏っていたことを認めます。
Zuishin

2020/02/13 01:46 編集

便宜的なものという意味がわかりませんが、オブジェクトはだいたい値です。変数に代入するときに便宜的に参照を用いることがあるということにすぎません。 「値型もオブジェクト」というより、変数に代入するときにシャローコピーするよう設計されたオブジェクト(他にも特徴はありますが)を値型と呼んでいるだけです。
tamoto

2020/02/13 01:57

Zuishin さん オブジェクトはだいたい値です。とは、「オブジェクトも最終的にはメモリ上の値」という意味なら間違いないです。 C# に限った話としますが、個人的には、値型の性質は設計によるものではなく、パフォーマンス上の理由でスタック領域を利用し高速に動作するデータ構造を独立で実装した上で、それをオブジェクトとしても扱えるように暗黙変換ルールを被せたことによるものと考えております。 その点で、本質的に異なるものを統一的に扱うためのハックに近いものだと感じています。
Zuishin

2020/02/13 02:04

「値」というのは計算の対象になるものを指して言いました。つまり式の引数や戻り値になりうるものです。オブジェクトという言葉自体がそれを意味していると思います。
momon-ga

2020/02/13 02:06 編集

とてもよいコメントたちですが、できれば回答にして欲しかったです。 もともと、言語で違うだろうとは思っていたので、以下ふくめて回答にしてもらえないでしょうか。 > ■聞きたいこと > 代入をシャローコピーというのか? > そのプログラミング言語は何か? > シャローコピーという根拠のようなものがあれば教えてもらいたい
momon-ga

2020/02/13 02:35

演算子オーバーライドすればディープコピーも可能とかでも全然かまわないので、回答が増えると有意義になるんじゃなかろうかと考えています。
tamoto

2020/02/13 02:42

Zuishin さん なるほど、理解しました。 自分が「値」と呼んでいたものは、実値 (変数が指し示すデータそのもの、あるいは参照「値」、即ちポインタ値) を考えておりました。 自分がこの「値」とは別に「オブジェクト」の存在を考えていたため、議論が噛み合っていなかったものと認識しました。 以上の内容を元に、回答を書き直しました。 momon-ga さん 先程回答を更新しました。疑問への答えとなっていますでしょうか。 できれば、あなたの立場や意見も聞きたかったです。
Zuishin

2020/02/13 03:03 編集

tamoto さんの新しい回答におおむね同意しますが、Ruby のところで参照とオブジェクトが混同されているように見えます。Ruby の現在のオブジェクトがすべて参照型であるというのと、Ruby ではオブジェクトと参照を同じものと定義するというのでは、まったく話が違ってきますが、この回答では後者に見えます。 https://magazine.rubyist.net/articles/0032/0032-CallByValueAndCallByReference.html この記事では Ruby のオブジェクトの値渡しについて述べられています。引数なので代入かと言うと微妙なところがありますが、シャローコピーが行われることになります。
Zuishin

2020/02/13 03:05

momon-ga さん、私が回答しても tamoto さんや maisumakun さんと同主旨の回答になると思いますので、控えることにします。
tamoto

2020/02/13 03:27

Zuishin さん 提示の記事を読みました。Ruby が値渡しであることは間違いないですが、その際にシャローコピーは行われていないと認識しております。 引数への代入前後において、仮引数のオブジェクト ID と実引数のオブジェクト ID は一致しています。 その場合において、この回答の記述では間違いとなりますでしょうか。
tamoto

2020/02/13 03:47

はい。自分にもそう見えていました。 Ruby は詳しくなくて申し訳ないのですが、その図は単純に間違っているように思えます。(もしくは省略されすぎている?) 数値型も参照であり、その参照値がコピーされている状況と等しい挙動をしていました。 同じオブジェクトへの参照を持つなら、オブジェクト ID が一致するのも納得できます。 もしかしたら、ランタイム側で数値型は特別に即値として扱うような最適化が行われていて、それを図にしていた、という可能性もありますが、そこまでは分かりませんでした。
Zuishin

2020/02/13 03:51

なるほど。ただ私の主旨としては、 > Ruby のような、全てのデータが参照である状況を指して「全てはオブジェクトである」と表現する に引っかかるということです。Ruby では参照であることがすなわちオブジェクトの定義になっている根拠が欲しいです。たまたま参照で実装されていても、それは本質的にオブジェクトとは無関係であるように思います。
maisumakun

2020/02/13 03:52

> もしかしたら、ランタイム側で数値型は特別に即値として扱うような最適化が行われていて、それを図にしていた、という可能性もありますが 実際にRubyではそのような最適化が入っています。
tamoto

2020/02/13 04:00

Zuishin さん 主旨理解しました。 そういう意味では、この回答の表現には不備がありますね。 誤解のない表現に修正を考えます。 maisumakun さん 補足ありがとうございます。 ということは、図解では最適化までを考慮したものを記載していたということですね。 そのような最適化が入っていたとしても、参照を扱っている場合と同等な挙動となるようにデザインされていることは自体は間違いではないと思いました。
guest

0

以下はPythonで定義上代入文です。

python

1>>> a = [1, 2, 3] 2>>> b = [] 3>>> id(a) 4140100099738760 5>>> id(b) 6140100099738632 7>>> b[:] = a 8>>> b 9[1, 2, 3] 10>>> id(b) 11140100099738632 12

7. 単純文 (simple statement) — Python 3.8.2rc1 ドキュメント

bの中にaを複製しているのでコピーです。この場合は再帰的に参照をたどって複製したりはしないのでシャローコピーです。
(一種のイロニーなので真に受けないでください。実はbのスライス表記への代入はbのメソッド呼び出しとして処理されます)


もっと常識的なシャローコピーは次のように書くことができます。

python

1>>> c = a.copy() # list.copyというメソッドがあるので都合よく使わせてもらう 2>>> c 3[1, 2, 3] 4>>> id(c) 5140100099686024 6

「すでに確保されている記憶領域に対して複製を行う」方法と「記憶領域を新たに確保してそこに複製を行う」方法とに一般化して捉えると概念を捉える上では手助けになるかもしれません。

投稿2020/02/13 02:54

編集2020/02/13 02:58
hayataka2049

総合スコア30935

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

momon-ga

2020/02/13 05:10

pythonは、ドキュメントがしっかりしてますね。 >>> b = a の場合は、”名前がすでに束縛済みの場合、再束縛 (rebind) がおこなわれます。”なので、idは、aと同じですが、サンプルにあるようにtargetの書き方で、動きが違うのですね。 回答ありがとうございました。
hayataka2049

2020/02/13 05:33

すみません、私の回答とそのコメントがどう繋がるかがわかりませんでした。 今回のサンプルでは再束縛は関係ありません。 b = aとb[:] = aはまったく異なる動作です。前者では再束縛が起きますが、後者では起きません。一般的なOOPの代入っぽいのは前者ですが、後者もPythonでは代入です。要するに「代入」で一概に議論するのは無理という主張です。
momon-ga

2020/02/13 08:21 編集

7. 単純文 (simple statement) にで、ターゲット(代入の左辺)によって挙動が動作が違うむね書いてありました。 ターゲットが識別子 (名前) の場合、スライスの場合など。 > 要するに「代入」で一概に議論するのは無理 はい。違うということを(targetの書き方で、動きが違う)と表現していました。 代入は、自分の中ではbind、またはrebindという認識が前提にあってシャローコピーに違和感がある というのが発端だったのですが、pythonの代入は挙動が複数あるというのを理解したという感じの意図で hayataka2049さんの例は、スライスだったので、識別子の例を記載して、挙動が異なる ⇒ なので、代入をひとくくりに語れないことを表したかったのです。
guest

0

代入をシャローコピーというのか?

言語やものによっては、単純な値を超えたものについても、代入がコピーになる例が存在します。PHPの配列、C++の参照でないオブジェクト型などです。

投稿2020/02/13 00:55

編集2020/02/13 01:02
maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

momon-ga

2020/02/13 05:10

回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問