none
STL vectorの要素をポインタにできる? RRS feed

  • 質問

  •  

    SLTのvectorの要素をポインタとしてmapなどのコンテナに格納し、何らかの処理を行うというのは、仕様的に問題ないのでしょうか?
    プログラムをデバッグしていてデバッグ版では正常に動作するのですが、Release版では正常に動作しません。
    他に原因があるのかもしれないのですが、下記のようなコードは問題がないのかどうか、そこから探っていきたいと思いまして質問させていただきました。
     環境:VC8 Professional Edition
             WindowsXP SP3

    具体的には下記のようなコードになります(1つの関数にまとめてしまったので、実際には意味のないコードですが)。

    class Factor
    {
    public:
         Factor() {}
         ~Factory() {}
          :
          :
         // IDの取得
         int getID() const { return m_id; }
         // 要素の設定
         void setElement(int elem) { m_element = elem; }
         // ポイントの追加
         void addPoint(POINT p) { m_shape.push_back(p); }
    private:
         int m_id;
         int m_element;
         std::vector<POINT> m_shape;
    };
     
    void func()
    {
        std::vector<Factor> factarray;
        for (int i = 0; i < 1000; i++)
        {
            Factor fact;
            // factの属性値の設定
                :
                :
            factarray.push_back(fact);
        }

        //
        // mapにfactarrayのIDとFactorのポインタを格納 →こんなことして大丈夫なのか???
        //
        std::map<int, Factor *> factmap;
        for (size_t i = 0; i < factarray.size(); i++)
        {
            factmap.insert(std::pair<int,Factor*>(factarray[i].getID(), &factarray[i]));
        }

        for (std::map<int,Factor*>::iterator it = factmap.begin(); it != factmap.end(); it++)
        {
                :
                :
                // 要素を設定
                it->second->setElement(100);   // factmapにもfactarrayにも影響はない???
                POINT p;
                p.X = 100; p.Y = 200;
                it->second->addPoint(p); // これも問題はない?
        }

        :
        :
    }

    よろしくお願いいたします。

    2009年2月26日 13:56

回答

  • kfsh の発言:
    SLTのvectorの要素をポインタとしてmapなどのコンテナに格納し、何らかの処理を行うというのは、仕様的に問題ないのでしょうか?

    問題ありません。

    ただ、map に格納した後で vector の途中に要素を挿入すると、挿入した場所以降の要素へのポインタは無効になります。削除も同様です。

    また、push_back や insert 等で vector の要素数が変化した時に、内部でメモリを再確保するような処理が入ると全ての要素へのポインタが無効になります。こちらは reserve を使えば対処できます。

    もし、map にポインタを格納した後で vector を操作しているなら、ポインタが無効になってしまうような処理をしていないかどうかを疑ってみると良いと思います。

    • 回答としてマーク sk7474 2009年3月12日 9:15
    2009年2月27日 5:08
  • std::vectorがメモリ確保し直したときアドレスが変わる恐れがありますね。
    こういう用途では、VS2008 SP1となってしまいますがstd::tr1::arrayでしょうか。
    コンパイル時に要素数を確定させるのでこのような問題は起きません。
    まぁvectorのサイズを変えないよう心がけるだけでもいいかもしれませんが。
    • 回答としてマーク sk7474 2009年3月12日 9:12
    2009年2月27日 13:00
  •   vectorでなくてもかまわんなら listで。
    listなら挿入/削除によってポインタ値が変わることはなかったハズ。

    επιστημη @わんくま同盟, Microsoft MVP Visual C++
    • 回答としてマーク sk7474 2009年3月12日 9:11
    2009年3月6日 23:06

すべての返信

  • kfsh の発言:
    SLTのvectorの要素をポインタとしてmapなどのコンテナに格納し、何らかの処理を行うというのは、仕様的に問題ないのでしょうか?

    問題ありません。

    ただ、map に格納した後で vector の途中に要素を挿入すると、挿入した場所以降の要素へのポインタは無効になります。削除も同様です。

    また、push_back や insert 等で vector の要素数が変化した時に、内部でメモリを再確保するような処理が入ると全ての要素へのポインタが無効になります。こちらは reserve を使えば対処できます。

    もし、map にポインタを格納した後で vector を操作しているなら、ポインタが無効になってしまうような処理をしていないかどうかを疑ってみると良いと思います。

    • 回答としてマーク sk7474 2009年3月12日 9:15
    2009年2月27日 5:08
  • std::vectorがメモリ確保し直したときアドレスが変わる恐れがありますね。
    こういう用途では、VS2008 SP1となってしまいますがstd::tr1::arrayでしょうか。
    コンパイル時に要素数を確定させるのでこのような問題は起きません。
    まぁvectorのサイズを変えないよう心がけるだけでもいいかもしれませんが。
    • 回答としてマーク sk7474 2009年3月12日 9:12
    2009年2月27日 13:00
  •   vectorでなくてもかまわんなら listで。
    listなら挿入/削除によってポインタ値が変わることはなかったハズ。

    επιστημη @わんくま同盟, Microsoft MVP Visual C++
    • 回答としてマーク sk7474 2009年3月12日 9:11
    2009年3月6日 23:06
  • こんにちは。中川俊輔 です。

    皆様、回答ありがとうございます。

    kfshさん、フォーラムのご利用ありがとうございます。
    その後いかがでしょうか?疑問は解決しましたか?

    勝手ながら、有用な情報と思われる回答へ回答マークをつけさせていただきました。

    今後ともフォーラムをよろしくお願いします。
    それでは!
    マイクロソフト株式会社 フォーラム オペレータ 中川 俊輔
    2009年3月12日 9:19