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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

4153閲覧

C++: 関数にポインタで渡す場合と、コピーする場合のメリット・デメリット

saito.kaz

総合スコア76

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2016/01/21 00:57

C++を初めてまだ一週間のものです。
Javaの場合、すべて値渡しだったので、なぜc++ではポインタとか参照渡しの設定があるのかいまいち、メリットが分かりません。

質問①
Javaの場合、関数内にオブジェクトの値渡しが行われると、コンストラクタが発動するのでしょうか。

質問②;
C++の場合、オブジェクトの値渡しの場合、コンストラクタが発動する言語仕様だから、ポインタや参照渡しが使われるのでしょうか。

質問③:
C++の場合、ポインタや参照渡しがあるので、処理が高速になるといわれるのでしょうか?

すいませんが、回答お願い致します。

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

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

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

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

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

guest

回答4

0

ベストアンサー

質問1: Javaの場合のオブジェクト引数の渡し方は、オブジェクトをコピーせずに渡す、「参照の値渡し」だけです。関数呼び出しのためだけに新たなオブジェクトを生成することはありません。

質問2: はい、C++はC言語からの派生ですが、C言語で「構造体がコピーしての値渡し」となっていたのを引きずってか、オブジェクトについても「コピーして渡す」のがデフォルトとなっています。参照やポインタを使わないと、「コピーせずに渡す」ことが再現できません。

質問3: 関数への引数の渡し方と性能は直接関係するものではありません(例えばPHPでは、配列が「コピーしての値渡し」ということになっていますが、Copy on writeといって、実際に書き込むまでコピーが発動しないようになっています)。

投稿2016/01/21 01:47

maisumakun

総合スコア145121

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

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

saito.kaz

2016/01/21 01:54

ありがとうございます。 勉強になります。
guest

0

こんにちは。

既に回答は網羅されていると思いますので、少し違う視点で補足してみます。

Javaの場合、すべて値渡しだったので、

まず、これが間違いです。Javaの場合、クラス型のインスタンスは原則参照渡しです。

JavaやC#は、クラス型のインスタンスを代入したり関数へ渡したりするとそのインスタンスを指すポインタがコピーされるだけでインスタンスそのものもはコピーされません。ほとんどのケースではこれで十分なので、無駄にコピーしないことで高速化を図っています。ディープコピーって言葉があるようにクラス型のインスタンスの内容をコピーする方が特別扱いです。

C++ではこれと逆で、クラス型のインスタンスを「代入」するとそのインスタンスの内容をコピーします。JavaやC#で言うディープコピーがデフォルトの動作なのです。
ということは、単にポインタをコピーしたい時は明示的に指定する必要が有るため、ポインタや参照の構文で指定するのです。

因みに、ディープコピーするためのC++のメソッドが「コピー代入演算子」や「コピーコンストラクタ」です。可能な時はコンパイラが自動的に作ってくれます。単純なクラスや構造体なら大抵自動的に作ってくれます。C++凄いでしょ?


【閑話休題】
個人的には、高速なプログラムを書くためにはポインタの概念を理解していることが必須と思います。
それを理解できない人でも低速なプログラムならかけるので、本来JavaやC#のデフォルトはディープコピーを選択するべきだったのでは?って感じます。
現状はポインタを理解しないと使えないC++でディープコピーがデフォルトで、ポインタを理解しないでも使えることを目指しているJavaやC#のデフォルトがポインタのコピーって変ですねよ。

投稿2016/01/21 03:03

Chironian

総合スコア23272

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

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

saito.kaz

2016/01/21 09:40

ありがとうございます。 とても参考になりました!
guest

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への値渡しのように見えますが、実際には参照渡しの振る舞いとなり、asは同一のオブジェクト・インスタンスを指します。

質問②;
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++ソースコード上で通常変数を代入(ここでは関数引数へ渡す操作)すると、どのような型であっても必ず値渡しが行われます。このとき、対象の型がclassstructであればコピー・コンストラクタが呼ばれます。

質問③:
C++の場合、ポインタや参照渡しがあるので、処理が高速になるといわれるのでしょうか?

この質問には「はい」とも「いいえ」とも答え難いです。ただし近年のコンピュータ・アーキテクチャでは、値型や値渡しという考え方は確かに重要視されており、Java言語にも将来的には値型が導入される可能性があります。

投稿2016/01/21 02:16

編集2016/01/21 02:18
yohhoy

総合スコア6189

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

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

saito.kaz

2016/01/21 02:18

ありがとうございます。 ベストアンサーの回答です。 ありがとうございます。
guest

0

C++がよくわからないので、1だけお答えします。答えは「NO」です。
Javaで参照型を関数(メソッド)などに渡す際には「参照の値渡し」などと表現されます。
例えばこんなコードにおいて…

java

1Hoge hoge = new Hoge();

オブジェクトが生成される際(new Hoge())、メモリ上にそのオブジェクトを保存するための領域が確保されます。そして変数hogeには、生成したオブジェクトが格納されているメモリ上の番地のような値が返されます。変数hogeが指すオブジェクトを使う際には、この値を使ってメモリ上のオブジェクトの実体にアクセスすることになります。
そして、これをメソッドに渡すときはその番地が渡されます。「このオブジェクトはここにあるよ」とメソッドに教えるようなイメージです。新たにコンストラクタを呼んでオブジェクトを生成しているわけではありません。
なので、ポインタを軽く調べた程度の私の知識でポインタと比較するなら、Javaの参照型変数はすべてポインタです。ただし、C++のポインタのようにポインタの値を直接操作することはできません。

投稿2016/01/21 01:43

swordone

総合スコア20649

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

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

saito.kaz

2016/01/21 01:54

ありがとうございます。 参考になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問