web-dev-qa-db-ja.com

C ++がstd :: vectorを初期化するために「新しい」ステートメントを必要としないのはなぜですか?

/* bar.h */
class bar{
    /* standard stuff omitted */
    std::vector<my_obj*> foo;
};

/* bar.cpp */
bar::bar(){ 
    // foo = new std::vector<my_obj*>(); <-- why don't I need this line??
    foo.Push_back(new my_obj());
}

Fooにstd :: vectorの新しいインスタンスを割り当てなかったのに、なぜこのコードが機能するのですか?

31
ash

C++はC#/ Javaではないからです。

std::vector<my_obj*> foo;

これはobjectの定義であり、C#/ Javaのような参照ではありません。オブジェクトは型の生きたインスタンスです。

new std::vector<my_obj*>()

この式はpointerを返します。 std::vector<my_obj*>*を返します。これはnotfooと同じ型です(末尾の*が違います)。 fooはオブジェクト、std::vector<my_obj*>*はオブジェクトへのポインターです。

オブジェクトには(ポインタや参照ではなく)特定の有効期間があります。 newを使用してオブジェクトへのポインターを作成した場合、deleteを明示的に呼び出すまで、ポイントされたオブジェクトの有効期間は残ります。オブジェクトを別のオブジェクトのメンバーとして作成すると、その内側のオブジェクトの寿命は(おおよそ)外側のオブジェクトの寿命を反映します。スタック上にオブジェクト(関数スコープのパラメーターまたは変数)を作成する場合、その有効期間はその変数名の現在のスコープです。

46
Nicol Bolas

barにはstd::vectorではなくstd::vector *が含まれているためです。

これは本当にこのようなものと違いはありません:

class bar
{
    int foo;  // No need to create a "new int"
};
6

Fooはポインターではなくオブジェクトだからです。

std::vector<my_obj*>    // This is an object
std::vector<my_obj*> *  // This is a pointer to an object
                    ^^^ // Notice the extra star.

新しいポインタを返します:

new std::vector<my_obj*>();  // returns std::vector<my_obj*> *

PS。ベクトルには、ポインタではなくオブジェクトが含まれている可能性があります。

std::vector<my_obj>   foo;
...
foo.Push_back(my_obj());

それ以外の場合は、ベクターがスコープ外になったとき(含まれているオブジェクトが破棄されたとき)に、ベクター内のすべてのオブジェクトを手動で削除する必要があります。つまり、ベクターにポインターを保持する場合は、次のいずれかを実行する必要があります。

// 1. Manually delete all the elements in the vector when the object is destroyed.
~bar::bar()
{
    for(std::vector<my_obj*>::iterator loop = foo.begin(); loop != foo.end(); ++loop)
    {
        delete (*loop);
    }
}

// 2. Use a smart pointer:
std::vector<std::shared_ptr<my_obj> >  foo;

// 3. Use a smart container for pointers
boost::ptr_vector<my_obj>   foo
5
Martin York

std::vectorがあなたのためにそれを行うので:)あなたはstd::vectorへのポインタを持っていないので、メモリを内部的に割り当てるstd::vector型のオブジェクトを設定するだけです。

3
ScarletAmaranth

このライブラリのstd :: vectorはポインタではありません

1
AAlkhabbaz

Fooはnewへのポインターではなくfooであるため、vectorvectorを使用する必要はありません(つまり、std::vector<my_obj*> *foo)。

JavaまたはC#から来ている場合は、std::vector<my_obj>(オブジェクトのベクトル)ポインターのベクトルの代わりに。本当に何をしたいかに依存します。

1
crashmstr

std::vector<my_obj *> foostd::vector<my_obj *> *fooとは異なります。 2番目のケースではnewを使用する必要がありますが、最初のケースでは使用しません。

0