Почему С++ не требует нового оператора для инициализации 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?


person ash    schedule 28.12.2011    source источник
comment
Что они сказали. Так же не могу порекомендовать foo.push_back(new my_obj()); ибо где вы там память освобождать собираетесь?   -  person Mr Lister    schedule 28.12.2011


Ответы (7)


Потому что C++ — это не C#/Java.

std::vector<my_obj*> foo;

Это определение объекта, а не ссылки, как в C#/Java. Объект — это живой экземпляр типа.

new std::vector<my_obj*>()

Это выражение возвращает указатель. Он возвращает std::vector<my_obj*>*, который не того же типа, что и foo (именно * в конце отличает их). foo — это объект, std::vector<my_obj*>* — указатель на объект.

Объекты (а не указатели или ссылки) имеют определенное время жизни. Если вы создаете указатель на объект с помощью new, время жизни объекта, на который он указывает, будет таким, пока вы явно не вызовете delete. Если вы создаете объект как член другого объекта, то время жизни этого внутреннего объекта будет (более или менее) отражать время жизни внешнего объекта. Если вы создаете объект в стеке (параметр или переменную в области действия функции), то его время жизни — это текущая область действия этого имени переменной.

person Nicol Bolas    schedule 28.12.2011

Поскольку bar содержит std::vector, а не std::vector *.

Это действительно ничем не отличается от чего-то вроде этого:

class bar
{
    int foo;  // No need to create a "new int"
};
person Oliver Charlesworth    schedule 28.12.2011

Потому что 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 возвращает указатель:

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
person Martin York    schedule 28.12.2011

Потому что std::vector делает это за вас :) У вас нет указателя на std::vector, вы просто настраиваете объект типа std::vector, который внутренне выделяет для вас память.

person ScarletAmaranth    schedule 28.12.2011

Вам не нужно использовать new для foo, так как foo - это vector, а не указатель на vector (т.е. std::vector<my_obj*> *foo).

Если вы пришли с Java или C#, вы можете рассмотреть возможность использования std::vector<my_obj> (вектор объектов) вместо вектора указателей. Это действительно зависит от того, что вы хотите сделать.

person crashmstr    schedule 28.12.2011

std::vector<my_obj *> foo отличается от std::vector<my_obj *> *foo. Во втором случае вам потребуется использовать new, а в первом нет.

person Pavan Yalamanchili    schedule 28.12.2011

std::vector в этой библиотеке не является указателем.

person AAlkhabbaz    schedule 28.12.2011