3

私はかなり大規模な C++ プロジェクトに取り組んでいますが、残念ながら C++ を最大限に活用できていません。コードの大部分は、ばかげた C++ クラスでラップされた単純な C のままです。

そこで、C++ と STL をいくつか導入して、コードをより読みやすく、より安全なものにしようとしました。

ただし、ベクトルをオブジェクト メンバーに割り当てると、奇妙なクラッシュ (正確にはデバッグ エラー) が発生します。これを想像してください:

class A
{

public:

    // Default constructor
    A()
    {
        initialize(std::vector<unsigned long>());
    };

    A(const std::vector<unsigned long> &data)
    {
        initialize(data)
    };

    ~A() {};

    void initialize(const std::vector<unsigned long> &data)
    {
        m_data = data;
    };

private:

    std::vector<unsigned long> m_data;

};

次に、コードの別の場所で、次のように呼び出します。

a.initialize(std::vector<unsigned long>());

ただし、プログラムはデバッグ エラーで終了します: vector iterators incompatible. この割り当てで発生します。

m_data = data;

...コピーを作成する必要があります。これが私がやろうとしていることです。

ただし、この行を次のように変更すると:

m_data = std::vector<unsigned long>(data);

...すべてが期待どおりに機能します。

私の質問は次のとおりです。なぜですか?そして、これは空のベクトルでオブジェクトを初期化する正しい方法ですか?

実際のクラスははるかに大きく、渡されるメンバーがはるかに多いことに注意してください。これが、初期化関数を使用する理由です。また、既存の配列を渡す可能性もあるため、空または既存のデータで初期化できる必要があります。

編集: クラッシュの原因が見つかりました。私が見ているコードは、実際には少し異なる動作をすることがわかりました:

A *pA = malloc(...); // Not really malloc but a wrapper for a WINAPI-Alloc
// Some stuff happens in between
pA->initialize(std::vector<unsigned long>());

したがって、実際には A のコンストラクターが呼び出されたことがないため、ベクター メンバー (m_data) のコンストラクターも実行されませんでした。そのため、宛先ベクトルがまだ構築されていないため、コピー関数を暗黙的に呼び出すときにコンストラクターの割り当てが機能し、クラッシュしました。さて、教訓を学び、改善するためのより恐ろしいコード:)

ありがとう!

4

3 に答える 3

3

表面的には問題ないように見えるので、なぜあなたのコードがそのエラーでクラッシュするのかわかりません。おそらく、質問を編集して最小限のテストケースを含める必要があります。

ただし、初期化を行うためのより良い方法があります。

class A
{
public:

    // Default constructor.
    // Relies on the fact that the default constructor for std::vector is
    // an empty vector.
    A()
    {}

    // Use the initialisation list.
    A(const std::vector<unsigned long> &data)
    : m_data(data)
    {}

private:
    std::vector<unsigned long> m_data;
};
于 2012-04-05T09:20:54.113 に答える
1

std::vectorコンストラクターは既に空のベクターを初期化しています。また、別の std::vector からデータを割り当てたい場合は、コピー コンストラクターを使用できます。

class A
{

public:

    // Default constructor
    A()
    {
        // Not required:
        // initialize(std::vector<unsigned long>());
    }

    // Make it explicit
    explicit A(const std::vector<unsigned long> &data)
      : m_data(data) // vector copy ctor
    {
    }

    ~A() {}


private:

    std::vector<unsigned long> m_data;

};
于 2012-04-05T09:22:01.513 に答える
0

コールは次のとおりです。

a.initialize(std::vector<unsigned long>());

が定義されている場所とは異なるライブラリでA? その場合、ライブラリの 1 つはデバッグ イテレータを有効にしてビルドされ、もう 1 つはそうではないと推測します。

于 2012-04-05T09:22:13.930 に答える