実現したいこと
配列を動的に割当てたい
前提
C++でスタックについて学んでいます。
スタックの内部データを可変にした際、配列の宣言がわからず質問しました。
静的な場合のソースコードを下記に示します。
C++
1#include <iostream> 2#include <assert.h> 3 4class stack { 5 private: 6 static const int max = 100; 7 int data[max]; 8 int sp; 9 10 public: 11 bool empty(); 12 void push(int); 13 int top(); 14 void pop(); 15 int size(); 16 stack(); // コンストラクタ 17 ~stack(); // デストラクタ 18}; 19 20bool stack::empty() { 21 return sp == 0; 22} 23 24void stack::push(int d) { 25 assert(sp <= max); 26 data[sp++] = d; 27} 28 29int stack::top() { 30 return data[sp-1]; 31} 32 33void stack::pop() { 34 assert(0 < sp); 35 --sp; 36} 37 38int stack::size() { 39 return sp; 40} 41 42stack::stack() {sp = 0;} 43 44stack::~stack(){} 45 46int main() { 47 stack s; // stack型変数の宣言 48 49 s.push(5); // メンバ関数の呼び出 50 s.push(8); 51 s.push(9); 52 std::cout << s.top() << std::endl; 53 54 s.pop(); 55 std::cout << s.top() << std::endl; 56 57 s.pop(); 58 s.push(3); 59 std::cout << s.size() << std::endl; 60 61 while(!s.empty()) { 62 std::cout << s.top() << std::endl; 63 s.pop(); 64 } 65 66 return 0; 67}
発生している問題・エラーメッセージ
エラーメッセージ /usr/bin/ld: /tmp/ccgJcVyl.o: warning: relocation against `_ZN5stack3maxE' in read-only section `.text._ZN5stackC2Ei[_ZN5stackC5Ei]' /usr/bin/ld: /tmp/ccgJcVyl.o: in function `stack::push(int)': EX1-4.cpp:(.text._ZN5stack4pushEi[_ZN5stack4pushEi]+0x1c): undefined reference to `stack::max' /usr/bin/ld: /tmp/ccgJcVyl.o: in function `stack::stack(int)': EX1-4.cpp:(.text._ZN5stackC2Ei[_ZN5stackC5Ei]+0x15): undefined reference to `stack::max' /usr/bin/ld: EX1-4.cpp:(.text._ZN5stackC2Ei[_ZN5stackC5Ei]+0x50): undefined reference to `stack::max' /usr/bin/ld: EX1-4.cpp:(.text._ZN5stackC2Ei[_ZN5stackC5Ei]+0x56): undefined reference to `stack::max' /usr/bin/ld: EX1-4.cpp:(.text._ZN5stackC2Ei[_ZN5stackC5Ei]+0x91): undefined reference to `stack::max' /usr/bin/ld: warning: creating DT_TEXTREL in a PIE collect2: error: ld returned 1 exit status
該当のソースコード
C++
1#include <iostream> 2#include <assert.h> 3 4class stack { 5 private: 6 static int max; 7 int *data = new int[max]; 8 int sp; 9 public: 10 bool empty() {return sp == 0;} 11 void push(int d) {assert(sp <= max); data[sp++] = d;} 12 int top() {return data[sp-1];} 13 void pop() {assert(0 < sp); --sp;} 14 int size() {return sp;} 15 stack(int sz = 100) { 16 sp = 0; 17 max = sz; 18 data = new int[max]; 19 std::cout << max << std::endl; 20 } 21 ~stack() {delete [] data;} 22}; 23 24int main() { 25 stack s; // stack型変数の宣言 26 27 s.push(5); // メンバ関数の呼び出 28 s.push(8); 29 s.push(9); 30 std::cout << s.top() << std::endl; 31 32 s.pop(); 33 std::cout << s.top() << std::endl; 34 35 s.pop(); 36 s.push(3); 37 std::cout << s.size() << std::endl; 38 39 while(!s.empty()) { 40 std::cout << s.top() << std::endl; 41 s.pop(); 42 } 43 44 return 0; 45}
試したこと
ポインタの書き方をいろいろ変えてみたのですが、うまくできませんでした。
補足情報(FW/ツールのバージョンなど)
実行環境
ubuntu 22.04 LTS
VS code
標準C++ライブラリに std::stack<T> がありますが、それを使わないのはナゼですか?
> 可変
の意味を明確にするのが良いのでは.
「可変」じゃない版は容量100のスタックだと見えますが,それに対して「可変」な版とはどう変わるのか?
・容量10や容量200のスタックも作りたい?(:各スタックの容量は固定)
・そのような容量制限無しにいくらでもpushできるようなのを作りたい?
・その他?
> ・容量10や容量200のスタックも作りたい?(:各スタックの容量は固定)
の場合,各スタックオブジェクトの容量が静的に定まるのであれば配列サイズをtemplateにする,動的に定まるのならサイズをコンストラクタ引数にでも受ける.
> ・そのような容量制限無しにいくらでもpushできるようなのを作りたい?
の場合,push時に内部配列容量が足りない場合は自動で拡張する(もっとでかい配列を生成して今の内容をコピーし,古い配列を捨てる)ような処理を入れる.
質問ありがとうございます!
すみません、std::stack<T>について調べてみたのですが、活用法がわかりませんでした、、。
使わない理由としては、課題の資料を参考にしているため、理解できていません、、。すみません、、。
一応課題の資料はを下記に掲載させていただきます。
https://ist.ksc.kwansei.ac.jp/~ishiura/xcpl/note/cpp1.pdf
この資料の課題1.4になります。
大きさ可変にしたいんだから max を削除してもちゃんと動くようにすればいいんじゃなくて?
コンストラクタで大きさを与えるんでしょ?
質問ありがとうございます!
一応可変の意味としては、「可変長のデータを扱える」という意味だと考えています。
(間違っていたらすみません、、)
教材の抜粋も掲載させていただきます。
「スタックの配列などの内部データは , 動的に割り当てても良い.(これによりスタックのサイズを可変にするなど ,可変長のデータが扱える.)」
>「可変長のデータを扱える」という意味だと考えています。
以下のどちらですか? それともほかのなにか?
- コンストラクタで最大要素数を指定できる。
- 要素が増えるにつれ内包する配列が自動拡張され、メモリの許す限りpushできる。
回答1件
あなたの回答
tips
プレビュー