[解決済み】なぜC++プログラマは'new'の使用を最小限に抑えなければならないのでしょうか?
質問
私は偶然に スタックオーバーフロー 質問 std::list<std::string> を使用した場合の std::string でのメモリリーク。 , および コメント にはこう書かれています。
使用停止
new
が多いですね。新しいものを使う理由がどこにもない。 ということです。で値によってオブジェクトを作成することができます。 C++ の一つで、これは この言語を使用する大きな利点です。
を割り当てる必要はありません。 ヒープ上のすべての
のような考え方はやめましょう。 ジャワ プログラマー
何を言いたいのかよくわからない。
でオブジェクトを値で作成する必要があるのはなぜか? C++ また、内部的にどのような違いがあるのでしょうか?
私が答えを誤解していたのでしょうか?
どのように解決するのですか?
広く使われているメモリ割り当て技術には、自動的な割り当てと動的な割り当てがあります。 一般的に、スタックとヒープという、それぞれに対応するメモリ領域があります。
スタック
スタックは常に順次にメモリを確保します。 これは、メモリを逆順に解放する必要があるためです(First-In, Last-Out: FILO)。 これは、多くのプログラミング言語におけるローカル変数のメモリ割り当て手法である。 最小限の簿記で済み、次に割り当てるアドレスが暗黙のうちに決まるため、非常に高速に処理できます。
C++では、これは
自動記憶
これは、スコープの終了時に自動的に保存を要求するためである。 現在のコードブロックの実行が開始されるとすぐに、(
{}
が完了すると、そのブロック内のすべての変数のメモリが自動的に回収されます。 また、この瞬間に
デストラクタ
が呼び出され、リソースの後始末が行われます。
ヒープ
ヒープを使用すると、より柔軟なメモリ割り当てモードが可能になります。 記帳はより複雑になり、割り当てはより遅くなります。 暗黙の解放ポイントがないため、メモリを手動で解放する必要があります。
delete
または
delete[]
(
free
C言語の場合)。 しかし、暗黙の解放点がないことが、ヒープの柔軟性の秘訣です。
ダイナミックアロケーションを使用する理由
ヒープを使用すると遅くなり、メモリリークやメモリの断片化を引き起こす可能性があるとしても、動的割り当ての方が制限が少ないので、完全に良い使用例があります。
ダイナミックアロケーションを使用する2つの主な理由。
-
コンパイル時に必要なメモリ量がわからない。 例えば、テキストファイルを文字列に読み込む場合、通常、ファイルのサイズが分からないので、プログラムを実行するまで、どれだけのメモリを確保すればよいのか判断できない。
-
現在のブロックを離れた後も持続するようなメモリを確保したい。 たとえば、次のような関数を書きたい。
string readfile(string path)
は、ファイルの内容を返すものです。 この場合、たとえスタックがファイルの内容全体を保持できたとしても、関数から戻って、割り当てられたメモリブロックを保持することはできません。
ダイナミックアロケーションが不要になりがちな理由
C++には
デストラクタ
. この仕組みにより、リソースの寿命と変数の寿命を一致させることで、リソースを管理することができます。この技法は
RAII
C++の特徴である。これは、リソースをオブジェクトにラップするものです。
std::string
がその典型例です。 このスニペットは
int main ( int argc, char* argv[] )
{
std::string program(argv[0]);
}
は、実際には可変量のメモリを割り当てます。 そのため
std::string
オブジェクトはヒープを使用してメモリを確保し、デストラクタでそれを解放します。 この場合、あなたが行ったのは
ない
は、手動でリソースを管理する必要がなく、動的メモリ割り当ての利点を享受できます。
特に、このスニペットでは、そのことを暗示しています。
int main ( int argc, char* argv[] )
{
std::string * program = new std::string(argv[0]); // Bad!
delete program;
}
不要な動的メモリ割り当てがあります。 このプログラムは、より多くのタイピングを必要とし(!)、メモリの割り当て解除を忘れる危険性があります。 このようなことをしても、明らかな利点はありません。
自動保存をできるだけ頻繁に使用すべき理由
基本的には、最後の段落に集約されています。 自動保存をできるだけ頻繁に使用することで、プログラムを作ることができます。
- 入力が速くなる。
- 実行時の速度が速い
- メモリやリソースのリークが少ない。
ボーナスポイント
参照された質問では、さらなる懸念事項があります。 特に、以下のクラスです。
class Line {
public:
Line();
~Line();
std::string* mString;
};
Line::Line() {
mString = new std::string("foo_bar");
}
Line::~Line() {
delete mString;
}
は、実は以下のものよりも、使うのにリスクが高いのです。
class Line {
public:
Line();
std::string mString;
};
Line::Line() {
mString = "foo_bar";
// note: there is a cleaner way to write this.
}
その理由は
std::string
はコピーコンストラクタを適切に定義しています。 次のようなプログラムを考えてみましょう。
int main ()
{
Line l1;
Line l2 = l1;
}
オリジナル版を使用すると、このプログラムはクラッシュする可能性が高いです。
delete
を同じ文字列で2回表示します。 修正版を使用すると、各
Line
インスタンスは自身の文字列を所有する
インスタンス
それぞれは独自のメモリを持ち、プログラムの終了時に両方とも解放されます。
その他の注意事項
を多用する。 RAII がC++のベストプラクティスとされているのは、上記のような理由からです。 しかし、すぐには明らかにならないが、さらなる利点がある。 基本的に、それは部分の総和よりも優れているのです。 機構全体が コンポーザー . スケールするのです。
を使用すると
Line
クラスをビルディングブロックとして使用します。
class Table
{
Line borders[4];
};
次に
int main ()
{
Table table;
}
が4つ割り当てられています。
std::string
インスタンス、4つの
Line
インスタンス、1
Table
インスタンスとすべての文字列の内容、そして
はすべて自動的に解放されます。
.
関連
-
[解決済み] [Solved] Error C1083: Cannot open include file: 'stdafx.h'
-
[解決済み] using namespace std;」はなぜバッドプラクティスだと言われるのですか?
-
[解決済み] static_cast, dynamic_cast, const_cast, reinterpret_cast はいつ使うべきですか?
-
[解決済み] なぜテンプレートはヘッダーファイルでしか実装できないのですか?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] JavaScriptの「new」キーワードとは何ですか?
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
-
[解決済み] template "と "typename "キーワードはどこに、なぜ入れなければならないのですか?
-
[解決済み] 型名の後の括弧は、newで違いがあるのでしょうか?
-
[解決済み】C++17の新機能は何ですか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Visual Studio 2015で「非標準の構文; '&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】リンカーエラーです。"リンカ入力ファイルはリンクが行われていないため未使用"、そのファイル内の関数への未定義参照
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] 配列のベクトルを扱う正しい方法