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

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

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

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

Q&A

解決済

2回答

2311閲覧

vectorを使わずに可変長配列

Giovannaaa

総合スコア10

C++

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

0グッド

0クリップ

投稿2020/10/06 02:14

このソースコードを作ってみたはいいのですがあまり理解ができておりません。
初めにnewで定義したcounterは0なのですがcounter++をすると増えていきます。なぜでしょうか?
もう一つはポインタを使わずにa[couter]とすれば実行するとおかしい結果になってしまいます。なぜポインタを使わないといけないのでしょうか?
よろしくお願いします。
出力結果
整数を入力せよ(終了は9999)
11
63
45
78
9999
X[0]=11
X[1]=63
X[2]=45
X[3]=78

C++

1 2#include<iostream> 3using namespace std; 4int main(){ 5 cout << "整数を入力せよ(終了は9999)" << endl; 6 int counter=0; 7 int *p; 8 p = new(nothrow)int[counter]; 9 10 while(true){ 11 int number; 12 cin >> number; 13 if(number == 9999) break; 14 p[counter]=number; 15 counter++; 16 } 17 18 for(int i=0; i<counter; i++){ 19 cout << "X[" << i << "]=" << " " << p[i] << endl; 20 } 21} 22 23

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

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

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

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

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

dodox86

2020/10/06 02:24

> このソースコードを作ってみたはいいのですがあまり理解ができておりません。 最初から理解してないけどコードを書き進めたので自分の書いたコードを解説してほしい、と言う質問でしょうか? それとも書いたはいいが、一応動いているように見えるのでなぜなのか解説してほしい、と言う質問でしょうか。(実際、たまたまエラーが無く、動いているように見えているだけです)
Giovannaaa

2020/10/06 02:31

実際動いています。なので自分の書いたコードを解説してほしいです。 よろしくお願いします。
kazuma-s

2020/10/06 03:03

4個ではなく、もっとたくさん(例えば 20個)入力したらどうなりますか?
Giovannaaa

2020/10/06 03:08

同じように20個の出力結果になります。
SHOMI

2020/10/06 03:47

たまたま動いているだけの範囲外アクセスコードです
Giovannaaa

2020/10/06 04:09

分かりました。ではvectorを使わずに可変長配列を作る事は可能でしょうか? よろしくお願いします。
fana

2020/10/06 04:27

あなたの言う「可変長配列」とは何か? 何を満たすべきなのか? 求められている機能とは何か? …といった事柄が自身の中で定まっているのでしょうか? ・YESの場合 → じゃあそれを実装すればよいのではないのか? ・NOの場合 → コードを書き始める前に,まず「何を作るのか」という話を具体的に決定すべき.
fana

2020/10/06 04:53

それはそれとして,質問内容自体がちょっと意味がわからない感じなので,回答が得られるようにするためには,そこを明らかにする必要がありそう. 質問内容は下記引用の2つであると思われる. (1) > newで定義したcounterは0なのですがcounter++をすると増えていきます。なぜでしょうか? (2) > ポインタを使わずにa[couter]とすれば実行するとおかしい結果になってしまいます。なぜポインタを使わないといけないのでしょうか? --- (1)に関して: 「newで定義したcounter」という記述の意味するところが不明です. 「"counter" が,"new"なるものによって"定義"された」という意味の記述であるように読めますが,それでは意味が通じません. (2)に関して: 突然出てきた "a" の正体が不明なので,意味が全く把握できない文章になっています.
guest

回答2

0

ベストアンサー

配列の大きさに 0 以下を指定してはいけません。 また、確保していないメモリにアクセスしています。 それによって起こる結果を言語仕様は「未定義」としていて、 C++ で言うところの未定義というのは予測不能な何かが起きることを許すという意味です。

クラッシュすることもあるかもしれませんし、変数の内容が異常なものになるかもしれませんし、一見して問題なく動いているように見えることもあるかもしれません。 故に未定義な動作が含まれるプログラムの挙動について (言語仕様に基づいて) 意味のある解説というものは出来ません

プログラマが問題のあるプログラムを書いてもコンパイル時に検出することが不可能 (またはとても困難) な場合も多く、しかし C++ は実行時にアクセス範囲をチェックするような余計なことを基本的にしません。 正しいプログラムなら必要のない処理だからです。 「ゼロオーバーヘッド原則」と呼ばれる C++ の言語設計の基本理念です。 (言語仕様としては要求しないということであって、処理系としては多少のチェックを入れる機能を持っている場合もあります。)

ですから、間違ったプログラムを書いてもそれが間違っているということが分かり難いです。 理解していないままに色々とやってみようという学習は C++ ではお勧めできません。 理解した上で手を動かして納得するというような段階を経る方が良いでしょう。


std::vector を使わずに可変長配列を作ることは可能ではあります。 std::vector は最初にある程度のメモリを確保しておき、それが足りなくなったらその時点で確保しているメモリの倍程度の大きさを別のところに確保しなおす (内容はコピーする) という形で実装されるのが普通です。 それを真似すればよいのです。

今の質問者のレベルだとそのようなものを作るのは難しいと思いますが……。

投稿2020/10/06 05:23

SaitoAtsushi

総合スコア5684

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

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

0

vector を使わず、メモリを確保しなおすことなく一度のメモリ確保で済ます
やり方が無いわけではありません。ちょっと問題がありますが。

C++

1#include <iostream> 2using namespace std; 3 4int make_array(int i, int* &p) 5{ 6 int number; 7 if (cin >> number && number != 9999) { 8 int n = make_array(i + 1, p); 9 p[i] = number; 10 return n; 11 } 12 p = new int[i]; 13 return i; 14} 15 16int main() 17{ 18 cout << "整数を入力せよ(終了は9999)" << endl; 19 int *p; 20 int counter = make_array(0, p); 21 for (int i = 0; i < counter; i++) 22 cout << "X[" << i << "]=" << " " << p[i] << endl; 23}

投稿2020/10/06 06:44

kazuma-s

総合スコア8224

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問