-8

現在、DirectX ゲームに取り組んでおり、定数バッファー コンストラクターで memset(0) (必要に応じて VS の ZeroMemory マクロ) を使用して、すべての値をゼロで初期化し、問題なく動作します。この方法でベクトルを含む他のスタクトを誤って初期化しようとしたときに問題が発生します。コンパイラ (VS2010/VS2012) によると、これにより「ベクトル イテレータに互換性がありません」、std::vector::end がより正確になります。memset がベクトル イテレータを無効にする可能性があることは理解できますが、要素をベクトルにプッシュした後、「終了」イテレータが正しく機能しないのはなぜですか。ベクトルの終了イテレータを正しい位置 (最後の要素の後) に再配置するべきではありませんか? すべての種類の std::some_container::end イテレータもこれの影響を受けますか?

#include <vector>

class MyClass
{
public:
    MyClass() { 
        memset(this, 0, sizeof(*this));
    }
    ~MyClass() {}
    std::vector<int>& GetData() { return m_data; }
    float            m_range;
private:
    std::vector<int> m_data;

};

int main()
{
    MyClass myClass;
    myClass.GetData().push_back(1);
    myClass.GetData().push_back(2);

    for (auto it = myClass.GetData().begin(); it != myClass.GetData().end(); it++)     
    {
        //stuff
    }
}
4

4 に答える 4

7

std::vector ベクトルを適切に初期化するデフォルトのコンストラクターがすでにあります。何もしないと、希望する動作が得られます。justを使用するmemsetと、未定義の動作が発生します。

メンバーをゼロに初期化するfloat場合、C++は次のようなコードでそれを提供します。

MyClass() : m_range(0) {}

C ++ 11でも書き込みfloat m_range = 0;が可能ですが、Microsoftのコンパイラはまだこの機能を実装していません。

関数は非常に粗雑なツールであり、のmem*ようなC++構造の中には場所がありませんstd::vectorstd::copy適切な初期化、、などの代替手段std::fillは、型システムを踏みにじらないため、優れたソリューションです。

于 2013-02-25T13:27:19.860 に答える
3

memsetコンストラクターを使用してクラスのオブジェクトを ing しないでください。

于 2013-02-25T13:24:48.553 に答える
2

代わりにこれを行ってください:

class MyClass {
public:
    MyClass() : range{} { 

    }

    float range;
    std::vector<int> data;
};

絶対に使用しないでくださいmemset、そして確かに絶対にthis神に使用しないでください。

プロのヒント:良い本を買う

于 2013-02-25T13:26:47.143 に答える
0

オブジェクトはmemsetの前に構築されるため、問題が発生します。

この方法でオブジェクトを初期化することは、C++では適切なアプローチではありません。

于 2013-02-25T13:28:03.983 に答える