C++を初めてまだ一週間のものです。
Javaの場合、すべて値渡しだったので、なぜc++ではポインタとか参照渡しの設定があるのかいまいち、メリットが分かりません。
質問①
Javaの場合、関数内にオブジェクトの値渡しが行われると、コンストラクタが発動するのでしょうか。
質問②;
C++の場合、オブジェクトの値渡しの場合、コンストラクタが発動する言語仕様だから、ポインタや参照渡しが使われるのでしょうか。
質問③:
C++の場合、ポインタや参照渡しがあるので、処理が高速になるといわれるのでしょうか?
すいませんが、回答お願い致します。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
ベストアンサー
質問1: Javaの場合のオブジェクト引数の渡し方は、オブジェクトをコピーせずに渡す、「参照の値渡し」だけです。関数呼び出しのためだけに新たなオブジェクトを生成することはありません。
質問2: はい、C++はC言語からの派生ですが、C言語で「構造体がコピーしての値渡し」となっていたのを引きずってか、オブジェクトについても「コピーして渡す」のがデフォルトとなっています。参照やポインタを使わないと、「コピーせずに渡す」ことが再現できません。
質問3: 関数への引数の渡し方と性能は直接関係するものではありません(例えばPHPでは、配列が「コピーしての値渡し」ということになっていますが、Copy on writeといって、実際に書き込むまでコピーが発動しないようになっています)。
投稿2016/01/21 01:47
総合スコア145121
0
こんにちは。
既に回答は網羅されていると思いますので、少し違う視点で補足してみます。
Javaの場合、すべて値渡しだったので、
まず、これが間違いです。Javaの場合、クラス型のインスタンスは原則参照渡しです。
JavaやC#は、クラス型のインスタンスを代入したり関数へ渡したりするとそのインスタンスを指すポインタがコピーされるだけでインスタンスそのものもはコピーされません。ほとんどのケースではこれで十分なので、無駄にコピーしないことで高速化を図っています。ディープコピーって言葉があるようにクラス型のインスタンスの内容をコピーする方が特別扱いです。
C++ではこれと逆で、クラス型のインスタンスを「代入」するとそのインスタンスの内容をコピーします。JavaやC#で言うディープコピーがデフォルトの動作なのです。
ということは、単にポインタをコピーしたい時は明示的に指定する必要が有るため、ポインタや参照の構文で指定するのです。
因みに、ディープコピーするためのC++のメソッドが「コピー代入演算子」や「コピーコンストラクタ」です。可能な時はコンパイラが自動的に作ってくれます。単純なクラスや構造体なら大抵自動的に作ってくれます。C++凄いでしょ?
【閑話休題】
個人的には、高速なプログラムを書くためにはポインタの概念を理解していることが必須と思います。
それを理解できない人でも低速なプログラムならかけるので、本来JavaやC#のデフォルトはディープコピーを選択するべきだったのでは?って感じます。
現状はポインタを理解しないと使えないC++でディープコピーがデフォルトで、ポインタを理解しないでも使えることを目指しているJavaやC#のデフォルトがポインタのコピーって変ですねよ。
投稿2016/01/21 03:03
総合スコア23272
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
Javaの場合、すべて値渡しだったので、なぜc++ではポインタとか参照渡しの設定があるのかいまいち、メリットが分かりません。
JavaとC++ではオブジェクトの扱いに関して、根底にある考え方が異なります。最大の違いは、オブジェクトをメモリ上で「スタック(stack)領域」と「ヒープ(heap)領域」のどちらに配置するかという違いがあり、Javaではこの違いをプログラマが意識することはありません(⇔使い分けができません)が、C++ではプログラマの責任で選択させます(⇔誤って使うとバグの温床)。
C++ソースコード上でこれらを使い分けるために、値型int
に対してポインタ型int*
や参照型int&
, int&&
が用意されます。Javaの場合は事情が異なり、プリミティブ型(int
など)と参照型(class
)で振る舞いが異なるという言語仕様になっています。これによりプリミティブ型では値渡しに、参照型では名前通り参照渡しになるという(少し混乱を招く)振る舞いになります。どちらが良い/悪いという話では無く、プログラミング言語設計時点でのトレードオフ選択かと思います。
質問①
Javaの場合、関数内にオブジェクトの値渡しが行われると、コンストラクタが発動するのでしょうか。
狭義には、Java言語にオブジェクト(参照型)の"値渡し"は存在しません。従ってコンストラクタは呼び出されません。
java
1String a = "ABC"; // オブジェクト"ABC" 2foo(a); // 関数fooへ参照渡しを行う 3 4void foo(String s) { 5 // 変数sはaと同じオブジェクト"ABC"を指している 6}
Javaソースコード上では変数a
から仮引数s
への値渡しのように見えますが、実際には参照渡しの振る舞いとなり、a
とs
は同一のオブジェクト・インスタンスを指します。
質問②;
C++の場合、オブジェクトの値渡しの場合、コンストラクタが発動する言語仕様だから、ポインタや参照渡しが使われるのでしょうか。
はい。
c++
1std::string a = "ABC"; // オブジェクト"ABC" 2foo(a); // 関数fooへ値渡しを行う 3 // このときコピー・コンストラクタが呼ばれる。 4 5void foo(std::string s) { 6 // 変数sは上記オブジェクト"ABC"とは別のオブジェクトを指す 7 // aもsも値としては文字列"ABC"だが、両者は異なるオブジェクト 8}
C++ソースコード上で通常変数を代入(ここでは関数引数へ渡す操作)すると、どのような型であっても必ず値渡しが行われます。このとき、対象の型がclass
やstruct
であればコピー・コンストラクタが呼ばれます。
質問③:
C++の場合、ポインタや参照渡しがあるので、処理が高速になるといわれるのでしょうか?
この質問には「はい」とも「いいえ」とも答え難いです。ただし近年のコンピュータ・アーキテクチャでは、値型や値渡しという考え方は確かに重要視されており、Java言語にも将来的には値型が導入される可能性があります。
投稿2016/01/21 02:16
編集2016/01/21 02:18総合スコア6189
0
C++がよくわからないので、1だけお答えします。答えは「NO」です。
Javaで参照型を関数(メソッド)などに渡す際には「参照の値渡し」などと表現されます。
例えばこんなコードにおいて…
java
1Hoge hoge = new Hoge();
オブジェクトが生成される際(new Hoge()
)、メモリ上にそのオブジェクトを保存するための領域が確保されます。そして変数hoge
には、生成したオブジェクトが格納されているメモリ上の番地のような値が返されます。変数hoge
が指すオブジェクトを使う際には、この値を使ってメモリ上のオブジェクトの実体にアクセスすることになります。
そして、これをメソッドに渡すときはその番地が渡されます。「このオブジェクトはここにあるよ」とメソッドに教えるようなイメージです。新たにコンストラクタを呼んでオブジェクトを生成しているわけではありません。
なので、ポインタを軽く調べた程度の私の知識でポインタと比較するなら、Javaの参照型変数はすべてポインタです。ただし、C++のポインタのようにポインタの値を直接操作することはできません。
投稿2016/01/21 01:43
総合スコア20649
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/01/21 01:54