- ベストアンサー
C言語でクラスの中でvectorを使う方法について
- C++の質問です。クラスの中でクラスをベクターで使うことはできますでしょうか?
- 画像にペイントしたものをラインごとに保存するプログラムを作っています。
- わからないことは1、ベクターで宣言したクラスの中身を個別にアクセスしたい。たとえば linesのpointにはA lineにはBといようにアクセスしたいです。説明がうまくできませんがアドバイスいただけたら助かります。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
>// lineは値渡しなので変更しても呼び出し元には影響しない >pl.line.swap(line);とありますが >pl.line = line;ではだめでしょうか?? それでもOKです。速度の問題が無ければ。 swap()はvectorが内部に持っているデータを、引数として渡された別のvectorと交換するメソッドです。 vectorの内部構造についてはさまざまですが、たいていの場合、動的確保されたメモリ領域へのポインタとその領域を管理するのに必要なデータで構成されています。 単なるコピーの場合、(必要なら)現在保持している領域の開放→コピー元と同じ大きさの領域確保→各要素のコピーという処理が行われます。これらはいずれも遅い処理です。 それに対して、swap()の場合、ポインタおよび管理データの交換だけなので上記と比較すると早い処理です。 それゆえ、コピー元を壊してもいいならばswap()のほうがコピー速度は速いです。 #ひょっとしたらとんでもない説明ミスがあるかもしれないので、その場合は訂正お願いします>ほかの回答者様 >またhitomuraさんが1から作ったコードと、改善していただいたコードの違いは速度の問題ですか? 内部処理については以下に書いたとおり速度の問題です。 しかし、追加用のデータ作成処理をpaintedlineクラスに移したのは、そのデータ作成方法はpaintedlineクラスだけが知っていればいいことであるためです。 また、paintedlineクラスの変数に直接アクセスできないようにしたのは、これらを外部から勝手に変更させないためです。 このあたりはオブジェクト指向プログラミングの原則の一つのカプセル化の基礎です。 >:iterator ite = line_.begin();などのあたりはまだ勉強したことがなかったです。 これはイテレーターといって、vectorの要素を指すためのクラスです。vectorの各要素に対するループを回すならばイテレーターを使ったほうが効率的になります。 今回の場合上下左右の初期値を決めるため特殊なことをやっていますが、 vector<Hoge> hoge; // === hogeに要素を追加 === for(vector<Hoge>::iterator ite = hoge.begin();ite != hoge.end(); ite++){ // 各要素に対する処理:要素のデータはポインタと同じように->で取得する } という具合にすれば最初から最後までの要素に対するループを回せます。 STLの効率的な使い方についてはスコット・メイヤーズの『Effective STL』にまとめられていますので、一読されることをお勧めします(参考URL:Amazon.co.jpの同書ページへのリンク)。 ただ、STLの入門書ではないため、STLの基礎についてはほかの本を読んだほうがいいでしょう。
その他の回答 (3)
- D-Matsu
- ベストアンサー率45% (1080/2394)
Tvectorとか書いてあるのがよくわかりませんが、std::vectorなら動的なサイズ変更が可能であることを除けば扱い方は普通の配列とほとんど変わりません。 ですからクラス内にvectorを持つことも、クラスをvector化することももちろん普通にできます。 #ただし自作クラスの場合はコピーコンストラクタを書いておいた方が無難。 AとかBとかいう話はもっと具体的に書いてもらわないと何とも言い難いんですが、個別アクセスというのは「vectorの各要素にアクセス」とは何か違うんでしょうか?
お礼
説明が不足していてすみません.なんとか問題が解決できました.
- hitomura
- ベストアンサー率48% (325/664)
関数1個しか書かないけど、こんな感じでどうでしょう。 //線を保存--------------クリックしてから離すまで void line_group::saveline(Tvector2<int>point, vector<Tvector3<int>> line){ // lineが空なら何もしない if(line.empty()) return; paintedline pl; //線の四隅を保存 for(int i=0; i<(int)line.size(); i++){ // 最初のループでは四隅の値が不定なので初期化 if(i == 0){ pl.top = pl.bottom = line[i].y; pl.left = pl.right = line[i].x; continue; } if(pl.top>line[i].y) pl.top = line[i].y; if(pl.botton<line[i].y) pl.botton = line[i].y; if(pl.left>line[i].x) pl.left = line[i].x; if(pl.right<line[i].x) pl.right = line[i].x; } pl.point = point; // lineは値渡しなので変更しても呼び出し元には影響しない pl.line.swap(line); //書かれた線を保存 lines.push_back(pl) } ……ただし、自分ならばこうします。 =line.h= #ifndef(LINE_H) #define LINE_H class paintedline{ private: //左上座標 Tvector2<int> point_; //上下左右の保存 int top_,botton_,left_,right_; //線の格納 vector<Tvector3<int>> line_; public: paintedline(const Tvector2<int>& point, const vector<Tvector3<int>>& line); // コピーコンストラクタと代入演算子は(多分必要だが文字数制限で入らないので)省略 //左上座標 const Tvector2<int>& get_point() const {return point_;}; //上下左右 int get_top() const {return top_;}; int get_bottom() const {return botton_;}; int get_left() const {return left_;}; int get_right() const {return right_;}; //線 const vector<Tvector3<int>>& get_line() const {return line_;}; } #endif//LINE_H =line.cpp= #include"line.h" paintedline::paintedline(const Tvector2<int>& point, const vector<Tvector3<int>>& line) :point_(point), line_(line) { if(line.empty()){ top_ = botton_ = left_ = right_ = 0; return; } top_ = bottom_ = line.begin()->y; left_ = right_ = line.begin()->x; vector<Tvector3<int>>::iterator ite = line_.begin(); ite++; for(;ite != line_.end(); ite++){ if(top_>ite->y) top_ = ite->y; if(botton_<ite->y) botton_ = ite->y; if(left_>ite->x) left_ = ite->x; if(right_<ite->x) right_ = ite->x; } }; =linegroup.cpp= //線を保存--------------クリックしてから離すまで void line_group::saveline(const Tvector2<int>& point, const vector<Tvector3<int>>& line){ lines.push_back(paintedline(point, line); }
お礼
私の不十分な説明と、下手なコードで理解していただけたようでとても感謝しています。 // lineは値渡しなので変更しても呼び出し元には影響しない pl.line.swap(line);とありますが pl.line = line;ではだめでしょうか?? またhitomuraさんが1から作ったコードと、改善していただいたコードの違いは速度の問題ですか?:iterator ite = line_.begin();などのあたりはまだ勉強したことがなかったです。 分かりやすい説明で助かります。ありがとうございます。
- Tacosan
- ベストアンサー率23% (3656/15482)
「クラスの中でクラスをベクターで使うこと」はできて当然. vector のインターフェイスはそんなに変態ちっくなものじゃないので, ここで使うくらいなら「こんな感じかな」と単純に考えればだいたいできるはず. でこのプログラムが何をしたいのかさっぱりわからんのだけど, 少なくとも void line_group::saveline(Tvector2<int>point, vector<Tvector3<int>> line) の中身が*あまりにもおかしい*ことはわかる. むしろ「line.x」などと書けると考えた理由を知りたい.
お礼
自分自身理解していないため、質問が不明確になってすみません。 Tvector3は自分で作った3つの変数を持つ構造体です。 line.xで変数をとりだしています。 上手く伝えられるように、理解できるように自分自身もっと勉強をします。
お礼
遅くなりましたが,詳しい説明ありがとうございました. なんとか目的のものが完成できました.紹介していただいた本も確認してみます.