[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
質問
私はJava出身で、C++でオブジェクトを扱うようになりました。しかし、一つ気になったのは、例えばこの宣言のように、人々はしばしばオブジェクトそのものではなく、オブジェクトへのポインタを使用することです。
Object *myObject = new Object;
よりも
Object myObject;
また、関数を使う代わりに、次のようにします。
testFunc()
, こんな感じです。
myObject.testFunc();
を書かなければならない。
myObject->testFunc();
しかし、なぜこのようにする必要があるのかが分かりません。メモリアドレスに直接アクセスできるので、効率とスピードに関係しているのだと思います。そうでしょうか?
どのように解決するのですか?
ダイナミックアロケーションを頻繁に目にするのは非常に残念なことです。これは、いかに多くの悪いC++プログラマーがいるかを示しています。
ある意味、2つの疑問が1つにまとまっているんですね。ひとつは、いつダイナミック・アロケーションを使うべきか、ということです。
new
)? もう一つは、いつポインターを使うべきか?
重要なメッセージは、次のとおりです。 常に仕事に適したツールを使用する . ほとんどすべての状況において、手動で動的割り当てを行ったり、生のポインタを使用するよりも、より適切で安全な方法があるはずです。
ダイナミックアロケーション
質問では、オブジェクトを作成する2つの方法を示しました。主な違いは、オブジェクトの保存期間です。オブジェクトを作成する際に
Object myObject;
つまり、オブジェクトはスコープ外に出たときに自動的に破棄されます。ブロック内で
new Object()
の場合、オブジェクトは動的保存期間を持ち、明示的に
delete
となります。動的保存期間は必要なときだけ使用するようにしましょう。
つまり
を使用する必要があります。
常に
可能であれば、自動保存期間を設定したオブジェクトを作成することをお勧めします。
.
ダイナミックアロケーションが必要となる主な状況は2つ。
- オブジェクトが現在のスコープより長持ちする必要がある場合 - その特定のオブジェクトのコピーではなく、その特定のメモリ位置にある特定のオブジェクトのコピーです。もし、オブジェクトのコピー/移動に問題がなければ(ほとんどの場合、そうすべきです)、自動的なオブジェクトを好むはずです。
- 大量のメモリを確保する必要がある スタックを埋め尽くすかもしれません。C++の権限外のことなので、これを気にする必要がなければいいのですが(ほとんどの場合、気にする必要はありません)、残念ながら、私たちが開発しているシステムの現実に対処しなければならないのです。
ダイナミックアロケーションが絶対に必要な場合は、スマートポインタなど、ダイナミックアロケーションを実行する型にカプセル化する必要があります。
RAII
(標準的なコンテナのように)。スマートポインターは、動的に割り当てられたオブジェクトの所有権に関するセマンティクスを提供します。以下の例を見てください。
std::unique_ptr
と
std::shared_ptr
などがあります。これらを適切に使えば、独自のメモリ管理をほとんど行わずに済みます (
ゼロの法則
).
ポインタ
しかし、生のポインタにはダイナミック・アロケーション以外にももっと一般的な使い方がありますが、ほとんどの場合、好みの代替手段があるはずです。以前と同様に 本当にポインタが必要でない限り、常に代替手段を選ぶようにしましょう。 .
-
参照セマンティクスが必要 . オブジェクトを渡す関数がその特定のオブジェクト(コピーではない)にアクセスできるようにしたいため、(どのように割り当てられたかに関係なく)ポインタを使用してオブジェクトを渡したい場合があります。しかし、ほとんどの場合、ポインタよりも参照型の方が適しています。なぜなら、参照型は特にそのために設計されているからです。これは、上記の状況1のように、必ずしも現在のスコープを超えてオブジェクトの寿命を延長することではないことに注意してください。先ほどと同じように、オブジェクトのコピーを渡しても問題ないのであれば、参照セマンティクスは必要ありません。
-
ポリモーフィズムが必要 . オブジェクトへのポインタや参照を通してのみ、ポリモーフィックに(つまり、オブジェクトの動的型に従って)関数を呼び出すことができます。もし、そのような動作が必要であれば、ポインタか参照を使う必要があります。繰り返しになりますが、リファレンスを使用することをお勧めします。
-
あるオブジェクトがオプションであることを表現したい を許可することで
nullptr
を渡すと、そのオブジェクトが省略されます。引数であれば、デフォルト引数や関数のオーバーロードを使うのが望ましいでしょう。そうでない場合は、できればこの動作をカプセル化した型、たとえばstd::optional
(C++17で導入 - 以前のC++規格ではboost::optional
). -
コンパイル時間を短縮するために、コンパイル単位を切り離したい。 . ポインタの便利な特性は、指し示す型の前方宣言だけが必要なことです(実際にオブジェクトを使用するには、定義が必要です)。これにより、コンパイル処理の一部を切り離すことができ、コンパイル時間を大幅に短縮できる可能性があります。詳細は Pimplイディオム .
-
C言語ライブラリとのインターフェイスが必要 またはC言語スタイルのライブラリです。このとき、生ポインタを使わざるを得なくなります。一番良いのは、生ポインタを解放するのは、可能な限り最後の瞬間にすることです。スマートポインタから生ポインタを得るには、例えば、スマートポインタの
get
メンバ関数です。もしライブラリがあなたに代わって何らかの割り当てを行い、ハンドルを使ってあなたがそれを解除することを期待するなら、あなたはしばしばそのハンドルをスマートポインターでラップし、独自のデレターでオブジェクトを適切に解除することができます。
関連
-
[解決済み】コンストラクターでのエラー:識別子を期待されますか?
-
[解決済み】識別子 "string "は未定義?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] なぜテンプレートはヘッダーファイルでしか実装できないのですか?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] 配列の場合、なぜ a[5] == 5[a] になるのでしょうか?
-
[解決済み] template "と "typename "キーワードはどこに、なぜ入れなければならないのですか?
-
[解決済み] マクロで無意味なdo-while文やif-else文を使っているのはなぜですか?
-
[解決済み】なぜC++プログラマは'new'の使用を最小限に抑えなければならないのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】coutはstdのメンバではない
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】識別子 "string "は未定義?
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】Enterキーを押して続行する
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み】Eclipse IDEでC++エラー「nullptrはこのスコープで宣言されていません」が発生する件