Почему C ++ не требует «нового» оператора для инициализации std :: vector? - PullRequest
30 голосов
/ 28 декабря 2011
/* 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?

Ответы [ 7 ]

46 голосов
/ 28 декабря 2011

Поскольку 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.Если вы создаете объект как член другого объекта, то время жизни этого внутреннего объекта будет (более или менее) отражать время жизни внешнего объекта.Если вы создаете объект в стеке (параметр или переменная в области действия функции), то его время жизни является текущей областью действия имени этой переменной.

6 голосов
/ 28 декабря 2011

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

Это действительно не отличается от чего-то подобного:

class bar
{
    int foo;  // No need to create a "new int"
};
5 голосов
/ 28 декабря 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 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
2 голосов
/ 28 декабря 2011

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

1 голос
/ 28 декабря 2011

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

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

1 голос
/ 28 декабря 2011

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

0 голосов
/ 28 декабря 2011

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

...