1

私はこのようなクラスを持っています

class variable
{
    public:
        variable(int _type=0) : type(_type), value(NULL), on_pop(NULL)
        {
        }

        virtual ~variable()
        {
            if (type)
            {
                std::cout << "Variable Deleted" <<std::endl;
                on_pop(*this);
                value=NULL;
            }
        }

        int     type;
        void*   value;
        typedef void(*func1)(variable&);
        func1 on_pop;
}

そして、次のようにインスタンスを std::vector にプッシュします。

stack.push_back(variable(0));

変数のデストラクタが呼び出されることを期待していますが、インスタンスがベクトルにコピーされるときに提供するコンストラクタが呼び出されることを期待しているため、型に値が割り当てられるまで if は入りません。しかし、何らかの理由でそうではありません。

stack.push_back を呼び出した後、(コピーの) デストラクタが実行され、コンストラクタが呼び出されなかった場合のように、タイプにランダムな値が含まれます。

私は自分が間違っていることを理解できないようです。助けてください!^_^

編集:

ここに、私が何を意味するかを示す自己完結型の例を示します。

#include <iostream>
#include <vector>

class variable
{
    public:
        variable(int _type=0) : type(_type), value(NULL), on_pop(NULL)
        {
        }

        ~variable()
        {
            if (type)
            {
                std::cout << "Variable Deleted" <<std::endl;
                on_pop(*this);
                value=NULL;
            }
        }

        int     type;
        void*   value;

        typedef void(*func1)(variable&);
        func1 on_pop;
};

static void pop_int(variable& var)
{
    delete (int*)var.value;
}

static void push_int(variable& var)
{
    var.type = 1;
    var.value = new int;
    var.on_pop = &pop_int;
}

typedef void(*func1)(variable&);
func1 push = &push_int;

int main()
{
    std::vector<variable>   stack;

    stack.push_back(variable(0));
    push(stack[stack.size()-1]);

    stack.push_back(variable(0));
    push(stack[stack.size()-1]);

    stack.push_back(variable(0));
    push(stack[stack.size()-1]);

    return 0;
}

上記のプログラムは、以下を出力します。

Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted
Variable Deleted

Process returned 0 (0x0)   execution time : 0.602 s
Press any key to continue.
4

2 に答える 2

4

RVO と NRVO へようこそ。これは基本的に、コンストラクターとデストラクターに副作用がある場合でも、オブジェクトが冗長である場合、コンパイラーがオブジェクトの作成をスキップできることを意味します。すぐにコピーまたは移動されて実際に存在するオブジェクトに依存することはできません。

編集: の実際の値はvector省略できません。variable(0)省略できるのは中間変数のみです。のオブジェクトは、vector通常どおり構築および破棄する必要があります。これらの規則は、一時的なものにのみ適用されます。

編集: なぜ独自のリソース管理クラスを作成しているのですか? unique_ptrカスタムのデリータで簡単に使用できます。自分の RTTI は?

破壊されたすべてのオブジェクトは構築されている必要があります。これに違反する標準の規則はありません。RVO と NRVO が問題になるのは、コンストラクタ/デストラクタでグローバルを変更する場合などです。それ以外の場合、プログラムの正確性には影響しません。それが彼らがスタンダードである理由です。あなたは何か他の間違ったことをしているに違いありません。

最終的に、WTF があなたに起こっているのか、なぜそれが機能しないのか、または「機能する」とはどういうことなのか、正確にはわかりません。SSCCE を投稿します。

編集:あなたのSSCCEに照らして、絶対に何も問題はありません。これは完全に予想される動作です。3 つのルールを尊重していません。つまり、デストラクタでリソースを破棄していますが、問題のリソースを実際に所有していることを確認する努力をしていません。コンパイラで生成されたコピー コンストラクターがロジックを爆破しています。Rule of Three、copy and swap、および C++ でのリソース処理に関する同様のイディオムについて読む必要があります。また、できれば、unique_ptrこれらの問題のない標準のようなスマート ポインターを使用することをお勧めします。

結局、variableスタック上に 3 つのテンポラリー、ベクター内に 3 つの 6 つのインスタンスを作成します。これらにはすべて、デストラクタが呼び出されています。問題は、コピー操作、コピーが何をするか、これらの一時ファイルに何が起こるかを考慮していないことです (ヒント: それらは破棄されます)。

の等しい例を考えてみましょう

int main()
{
    variable v(0);
    push_int(v);
    variable v2 = v;
    return 0;
}

変数vが構築され、新しいものが割り当てられ、intすべてがうまくいきます。しかし、待ってください-それから にコピーしv2ます。コンパイラによって生成されたコンストラクターは、すべてのビットをコピーします。次に、v2との両方vが破棄されますが、どちらも同じポインターを保持しているため、両方とも同じリソースを指しています。二重削除が多い。

std::shared_ptrコピー (共有所有権 - ) または移動 (固有所有権 - std::unique_ptr) セマンティクスを定義する必要があります。

編集:簡単なメモ。push私は、あなたが実際にアイテムに興味を持っていないことを観察しました. ただし、追加の要素を追加するときにベクトルのサイズを変更する必要があり、基本的な原因が同じである場合、同じ効果が観察されます。

デストラクタは 6 回呼び出されます。コンストラクターは 6 回呼び出されますあなたが意図したものではありません。

于 2012-05-26T09:07:25.950 に答える
0

Ok。私はさまざまなコンテナの組み込みについてもう少し読んでいますが、どうやら、ここで達成しようとしている仕事をするのはstd::dequeです。

于 2012-05-26T13:00:39.633 に答える