2

std::map を正しく使用する際に問題があります。クラスExampleは、ID、ラベル、キーポイントのベクトル、および記述子行列を持つクラスです。クラスExamplesは、ID を指定して例を取得するためのマップです。例は、ディスク上のファイルから読み取られ、マップに格納され、後で使用されます。

概念的には非常に単純ですが、マップを適切に埋めることができません。

私は次のクラスを持っています:

class Example
{
public:
    std::string id;
    std::string label;
    std::vector<cv::KeyPoint> keypoints;
    cv::Mat descriptors;

    Example(std::string id_, std::string label_)
        : id(id_), label(label_)
    {
        // ... nothing ...
    }

    string to_string() const
    {
        stringstream ss;
        ss << "@" << id
        << " (" << label << ")"
        << " - #keypoints " << keypoints.size()
        << ", descr " << descriptors.rows << " x " << descriptors.cols;
        return ss.str();
    } // to_string

}; // class Example

ostream& operator <<(ostream & out, const Example &ex)
{
    out << ex.to_string();
    return out;
} // operator <<

そしてこれ:

 // OLD: class Examples : public std::map<std::string, Example*> {
    class Examples {
    // New line after Martini's comment
    std::map<std::string, Example*> _map;
    [...]   
    void fill() {
       // create an example
       Example *example = new Example(id, label); 

       // inputstream in

       // Read all the keypoints
       cv::KeyPoint p;
       for(int i=0; ... ) {
            in.read(reinterpret_cast<char *>(&p), sizeof(cv::KeyPoint));
            example->keypoints.push_back(p); // push_back copies p
       } // for 

       // ... misc code

       cv::Mat descr(n_keypoints, d_size, cv_type, cv::Scalar(1));
       // ... read Mat from inputstream in, then assign it to the example
       example->descriptors = descr;


       // SEE THE OUTPUT BELOW
       std::cout << "INSERT THIS: " << (*example) << std::endl;
       _map.insert(std::pair<string,Example*>(id, example));
       std::cout << "READ THIS: " << *(get_example(id)) << std::endl;

       // ... other code
    } // fill

    // Code modified after Martini's comment.
    Example* get_example(const std::string &id) const {
        std::map<std::string, Example*>::const_iterator it = _map.find(id);
        if( it == _map.end()) {
            // ... manage error
            // ... then exit
        } // if
        return it->second;
    } // get_example


} // class Examples

insert/get 行からの出力は次のとおりです。

 INSERT THIS: @122225084 (label) - #keypoints 711, descr 711 x 128
 READ THIS: @122225084 (label) - #keypoints 0, descr 0 x 0

挿入文には、711 個のキーポイントと 711x128 の記述子マトリックスを含む例へのポインターがありました。挿入直後に ID を使用してサンプルを読み取ると、キーポイントが 0 で行列が空のサンプルへのポインターが得られます。

私は何を間違っていますか?

4

1 に答える 1

1

コードを調べると、考えられる説明の 1 つは、マップ内に同じキーを持つ要素が既にあるということです。まず、オブジェクトを追加する前とその後にポインターの値を出力することを診断するには (次のようなもの):

std::cout << "INSERT THIS: " << (void *)example << " " << (*example) << std::endl;
_map.insert(std::pair<string,Example*>(id, example));
std::cout << "READ THIS: " << (void *)get_example(id) << " " << *(get_example(id)) << std::endl; 

次または別の方法は、挿入の結果を確認することです。

if( !_map.insert(std::pair<string,Example*>(id, example)).second ) 
    std::cout << "ERROR: example:" << id << " is already there";

要素を無条件にオーバーライドしたい場合は、oprator[] を使用できます。

_map[ id ] = example;

本当に重複がある場合は、メモリ リークが発生します (いずれにしても発生します) ので、マップにデータを格納するためにスマート ポインターを使用することを強くお勧めします。

于 2013-02-23T03:19:25.670 に答える