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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C++

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

Q&A

解決済

4回答

902閲覧

new演算子について

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

0グッド

1クリップ

投稿2021/09/06 07:07

編集2021/09/06 07:25

New演算子をつかうコードをよく見ますが、(以下参照。)なぜ、new演算子を使わないといけないのかわかりません。
また、変数宣言なら、スタック、new演算子なら ヒープ領域確保する。
こちらの、スタック、ヒープ領域の意味がよくわかりません。

#include <iostream>

int main()
{
int buf = 100;

//これはできない //int nums[buf]; int *nums = new int[buf]; for (int i = 0; i < buf; i++) { nums[i] = i; } std::cout << nums[0] << std::endl; std::cout << nums[50] << std::endl; std::cout << nums[99] << std::endl; //newしたものはdeleteする delete[] nums; std::cin.get();

}

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

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

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

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

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

maisumakun

2021/09/06 07:11

どういう答えを求めていますか?
退会済みユーザー

退会済みユーザー

2021/09/06 07:26

修正しました。 new演算子を使う理由がわからないです。 またスタック、ヒープ領域の言葉の理由もわかりません。
fana

2021/09/06 07:30

> //これはできない のだから,しかたねぇ,newでやるか,っていう. (…じゃ「理由」としてダメなのかな?)
fana

2021/09/06 07:49

> スタック、ヒープ領域の意味 言葉の意味については「ヒープ領域 スタック領域」とかで検索したらどうです?
退会済みユーザー

退会済みユーザー

2021/09/06 08:03

調べたのですが、納得いく回答がありませんでした。
K_3578

2021/09/06 08:11

その調べた回答の腑に落ちない点を追記した方が良かったのでは? その方が回答者も一から説明するより楽だろうし
guest

回答4

0

newを使う理由:

このコードについて言えば,

//これはできない
//int nums[buf];

とご自身で言っているじゃないですか.
ある方法ではできないのだから,何かしらそれとは別の方法でやるしかない.
(とにかく,言語の仕様的に許してくれないのだから仕方ない)

で,その別の方法が new だった.
このコードでnewを使っている理由」はその程度のことでしょう.

スタック、ヒープ領域の意味がよくわかりません

こちらについては「とにかくたくさん検索してください」と言うのが手っ取り早いと思う.
(投げやりな回答というわけじゃなくて,いくつも説明が見つかると思うから)


で,それはそれとして,

//スタック領域が使われる? SomeType Instance;

//ヒープ領域が使われる? SomeType *pInstance = new SomeType();

の違いを実際上考える際には,
主たる関心はオブジェクトの生存期間に関する事柄なのであり,「なんとか領域が使われる(らしいぜ)」とかいう話は正直割とどうでもいい.

領域の種類に関して考えることがあるとしたら,
「スタック領域」のサイズというのは(一般に?)そこそこ小さくて,「使いすぎていっぱいになっちゃった」ということが(他種の領域と比べて)起きやすいので,それを避けるために,巨大なオブジェクトは「スタック領域」じゃない領域が使われるようにしてやるぜ!
…っていう話はある.
(逆に言えば,「スタックあふれちゃった」状態にまず到達しないだろうと見込めるならば,そのことをnewを使う理由にする必要は無い)

投稿2021/09/06 08:30

fana

総合スコア11996

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

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

0

ベストアンサー

まず、通常、文字列や数値などのデータはスタック領域(Stack area) に保存されます。
でも、このスタック領域、サイズが決まっており、整数一個とかなら問題ありませんが、

Webブラウザのタブみたいに複数必要だったり、構造体やクラスとかのような、物によっては相当デカいものだと、保持するのが大変です。

そこで、ヒープ領域(Heap area) と呼ばれる場所で、動的に確保する事で、メモリが許す限り保持できます。

ただし、これにも欠点があり、「自分でお片付けしないといけない」というのがあります。

スタック領域だと、関数のブロックから抜けるとかのような、「もうこれ以上使わんだろ」と思う場合は勝手にデリートされます。(返還される)

でも、ヒープ領域は開発者自身が「この領域にあるデータを破棄せよ」と命じないとずーーーーっと残ったままです。
(OSによっては実行ファイルが終了するとOS自身が破棄してくれるようですが)

その「ヒープ領域のここからこの分確保するぞ!」っていうのはC言語だとmalloc, C++だとnewに相当するものです。

「あー、(ヒープ領域の)ここにあるデータ、もう使わないから破棄だわ」というのがC言語だとfree, C++だと delete に相当するものです。

(ちなみにJavaとかのような言語だと、ガーベージコレクタ(GC)と呼ばれるものがdeleteしてくれるようです)

仮に、実行ファイルが閉じられるとOSがお片付けしてくれるとしても、
Webブラウザや常駐型のものだと、そこの部分はずーーーーーーっとあるので、メモリをひっ迫してしまいます。

なのでnewをするのなら、不必要になればdeleteするのがマナーです。

参考: メモリの動的確保(配列など)

そして、今回のコードですね。

今回のコードを見ると、

C++

1int buf = 100; 2 3int *nums = new int[buf];

となっていますね。

これは、動的にメモリ、つまりヒープ領域を確保しています。

で、最後は不要になったので、deleteで破棄。

要素数がはっきりとわかっている場合は普通の配列でもいいですが、要素数が実行時にしかわからないこともあります。
さらに、構造体やクラスの配列 ( Class1 objs[100] のような ) の場合もあります。

構造体やクラスなんかはメンバの分だけ重くなります。
(メンバ関数は関係ないっぽいが)

スタック領域だとその分ひっ迫します。

サイズによってはオーバーフローを起こします。

そのため、サイズが(実行するまで)不定だったり、オブジェクトのサイズがデカい場合はヒープ領域に確保する事があります。

int型とかだと 4バイトとかなのですが、構造体やクラスの場合はメンバ(メンバ変数)分、必要になるので、C++だとnew/deleteで確保する事が多いのです。

それを見習って(?) Javaとかでは new を使う方式でやるようです。


[追記1]

※ 他の回答者の方のアンサーを見て、ちょっと思ったので追記。

確かに単純にデータ列を確保するのなら new/deleteよりも std::vectorやstd::listを使ったりしますね。

ですが、クラスオブジェクトを生成する場合は良く使います。(モダンなものだとスマートポインタと呼ばれる、std::shared_ptr とかを使うようですが)

単純にint型データの配列のような場合はnew/deleteをするぐらいならstd::vectorを使います。

投稿2021/09/06 08:04

編集2021/09/06 08:08
BeatStar

総合スコア4962

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

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

退会済みユーザー

退会済みユーザー

2021/09/06 08:23

クラスオブジェクトの時に使う理由は、やはり、容量が多いためですか?
BeatStar

2021/09/06 08:31

あ、もう一つありました。 「他のクラスや関数でも使う場合」ですね。 容量の問題も一つの理由です。
退会済みユーザー

退会済みユーザー

2021/09/07 02:45

ありがとうございます。
fana

2021/09/07 02:53

> 「他のクラスや関数でも使う場合」 (これ,書き手側が思っている意味が,読み手側にうまく伝わってるのだろうか…?)
guest

0

なぜ、new演算子を使わないといけないのかわかりません。

これはnew-deleteの教科書的な例です。

実用的には、(よほど性能やメモリ消費に対する要求が強く、細やかな制御が必要となる場合は別ですが)C++ではvectorarrayのようなSTLコンテナを使ったほうが便利で安全なコードが書けます(自分でnewを書く必要もありません)。

「要素数が不明だ」というだけでnewを使うのはおすすめできません。

投稿2021/09/06 07:33

maisumakun

総合スコア146018

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

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

退会済みユーザー

退会済みユーザー

2021/09/06 07:40

実用的には、(よほど性能やメモリ消費に対する要求が強く、細やかな制御が必要となる場合は別ですが) 上記の理由は、ヒープ領域に確保するからですか? 変数宣言であれば、スタックに確保されると書いてありました。 ヒープとスタックの違いが判らなく、理解できません。
maisumakun

2021/09/06 07:47 編集

> 上記の理由は、ヒープ領域に確保するからですか? メモリ領域の違いとは無関係です。 STLはクラスなので、「あとから広げる」「要素数を取得する」等の操作もついてきますが、配列に対するnewはただメモリを取ってくるだけで、要素数をあとから知る手段すら存在しません。
退会済みユーザー

退会済みユーザー

2021/09/06 07:55

んー。そしたらnew演算子はあまり使わないということでしょうか? STLを使うより、new演算子を使ったほうが、後で、メモリが解放されると記載がありましたので、 こちらのほうがいい気がします。 何か間違っていることがありましたら、ご教示お願いします。
maisumakun

2021/09/06 07:57

> STLを使うより、new演算子を使ったほうが、後で、メモリが解放されると記載がありましたので、 こちらのほうがいい気がします。 STLも不要になればメモリを解放することが可能ですし、変数がスコープを抜ければ自動で解放されます。deleteを書く必要もありません。
退会済みユーザー

退会済みユーザー

2021/09/06 08:02

あ、そっか。どっちみち解放はされますね。失礼しました。 ひとまず、大丈夫です。 ありがとうございました。
maisumakun

2021/09/06 08:06 編集

> んー。そしたらnew演算子はあまり使わないということでしょうか? そうですね、(性能・メモリ的な要求や他所との互換性など理由がある場合を別として)スマートポインタやSTLなどで生のポインタに触らずプログラミングをするスタイルがいいかと思います(むろん、生のポインタを返すnewの出番もなくなります)。
fana

2021/09/06 08:39

> STLを使うより、new演算子を使ったほうが… 何か誤解があるようにも見えます. new と STL という全く違う方法があるわけじゃなくて, ざっくり言えば,STLのvectorだとかスマートポインタだとかいうやつらは「newやdeleteを使う仕事をうまいことやってくれる既存実装」です. 自分でnewとdeleteを直接使ってちまちま書く作業はわりとつらいし,また,そこそこしくじりやすいので,用途に即した既存実装が用意されているならそっちを使う方が楽だよね,っていう話ですね. (そうすることで,コードの見た目上には newやdeleteがあまり出てこなくなる.)
guest

0

[ご参考] スマートポインタを使うと...

C++

1#include <iostream> 2#include <memory> // unique_ptr, make_unique 3 4int main() { 5 int buf = 100; 6 7 //これはできない 8 //int nums[buf]; 9 10 std::unique_ptr<int[]> nums = std::make_unique<int[]>(buf); 11 12 for (int i = 0; i < buf; i++) { 13 nums[i] = i; 14 } 15 16 std::cout << nums[0] << std::endl; 17 std::cout << nums[50] << std::endl; 18 std::cout << nums[99] << std::endl; 19 20 std::cin.get(); 21 22 // "newしたものはdeleteする"のは unique_ptr まかせ 23}

投稿2021/09/06 23:16

episteme

総合スコア16612

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問