2

私のプロジェクトには、次の 2 つのクラスがありますEarleyParser

class EarleyParser
{

    public:

        EarleyParser();
        virtual ~EarleyParser();

        void initialize( string filePath, bool probabilityParse );

    private:

        bool probabilityParser;

        typedef unordered_map< string, list<Production> > productionHashTable;
        productionHashTable earlyHashTable;

};

そしてProductionクラス:

class Production
{
    public:

        Production();

        Production( float productionProbability, int productionLength, vector< string >* productionContent );

        Production( const Production& copy_me );

        virtual ~Production();

        float getProductionProbability();
        int getProductionLength();
        vector< string >* getProductionContent();

    private:

        float productionProbability;
        int productionLength;
        vector< string >* productionContent;

        void setProductionProbability( float productionProbability );
        void setProductionLength( int productionLength );
        void setProductionContent( vector< string >* productionContent );

};

上記のように、EarlyParserクラスには であるメンバー要素がありunordered_map、そのキー要素は文字列で、値はクラスlistの要素のです。Production

コードは正しく機能し、unordered_maplistが読み込まれますが、 の標準デストラクタ クラスを呼び出すとEarleyParser、セグメンテーション エラーが発生します。

私が理解しているように、のデフォルトのデストラクタは、EarleyParserのデフォルトのデストラクタを呼び出すunordered_map必要がlistあり、その要素のそれぞれに対してProductionクラスのデフォルトのデストラクタを呼び出す必要があります。これは次のとおりです。

Production::~Production()
{
    if( this->productionContent != NULL )
        delete this->productionContent; <- line 44
}

EarleyParser.cppValgrind と GDB を使用したバック トレースでは、デストラクタの 44 行目で正確に指定されているセグメンテーション エラーを解決する方法について、あまり役に立ちませんでした。

デストラクタ クラスを実装する必要がありますか、それともデフォルトのデストラクタで問題ありませんか? セグメンテーション違反の原因について何か考えはありますか?

追加されたコピー コンストラクター

Production::Production( const Production& copy_me )
{
    if( this->productionContent != NULL )
        this->productionContent = NULL;

    this->setProductionProbability( copy_me.productionProbability );
    this->setProductionLength( copy_me.productionLength );

    this->setProductionContent( copy_me.productionContent );

}
4

4 に答える 4

4

三つのルールは不完全です。ポインタメンバーがあるので、コピーコンストラクタコピー代入演算子、およびデストラクタが実装されていることを確認する必要があります。

さて、あなたはメンバーへのポインタを持っているので、あなたはそれを持っているべきではなく、代わりにaまたはを持っているべきだvectorとあなたに言うつもりです。std::vector<std::string>std::unique_ptr<std::vector<std::string> >

コンテナへのポインタを保持する必要があるとあなたが判断した理由はわかりませんが、それはほとんどの場合正当な理由ではなく、エラーが発生しやすいです。

コンテナへの参照を保持することもできますが、コンストラクタで初期化されていることを確認する必要があります。

ポインタの問題は、「解決策」として簡単に取得できないことですが、実際には非常にエラーが発生しやすく、使用が困難です。ポインターについて考えるのをやめ、毎回ポインターを使用する傾向がなくなった場合は、はるかに簡単にポインターを使用できるようになります。

于 2012-10-02T12:33:55.713 に答える
1

ProductionContent変数の初期化が表示されません。イニシャライザを使用してNULLに初期化してみてください。初期化されていないメンバー変数のデフォルト値はnullではありません。

これが意味するのは、productionContent!= NULLは、最初はNULL以外のものであるため、常にtrueになるということです。

すべてのコンストラクターで次のようなことを試してください。

Production::Production( const Production& copy_me ) : productionContent(NULL)
{
...
于 2012-10-02T12:34:05.123 に答える
1

2つのオプションがあります。

  1. でベクトルを動的に割り当てるかProduction、その場合、ベクトルポインタのディープコピーを実行するために代入演算子が必要です。コピーコンストラクタも同じようにする必要があります。この場合、三つのルールに従う必要があります。

  2. または、Productionコンストラクターでベクトルへのポインターを取得し、ディープコピーを実行しProductionません。この場合、ベクトルを所有していないため、デストラクタでベクトルを削除しないでください。

ケース1の場合は、ポインタを削除してstd::vectorby値を保持することをお勧めします。

于 2012-10-02T12:30:33.500 に答える
0

ポインターの正当な理由または悪い理由は、std :: shared_ptr(メンバーおよびコンストラクターパラメーターとして)を使用します。実行する回数が少ないほど、実行量は多くなります。std :: shared_ptrはnullptrを作成し、削除します!

于 2012-10-02T13:04:46.070 に答える