C ++ стандартный шаблон библиотеки векторного вопроса - PullRequest
0 голосов
/ 03 марта 2011

Может кто-нибудь объяснить по-английски, что здесь происходит?

std::vector<Cat*> cats; //I get that cats is a vector of Cat objects

if (std::find(cats.begin(), cats.end(), morris) == cats.end()) {
   cats.push_back(morris);
}

Ответы [ 6 ]

5 голосов
/ 03 марта 2011

@ mlimber уже дал одно объяснение.

Я бы объяснил это немного по-другому.Проще говоря, это способ взять что-то действительно простое:

 std::set<Cat> cats;

 cats.insert(morris);

и сделать его медленнее (линейным, а не логарифмическим) и значительно труднее читать или понимать.

Редактировать: Справедливо, Я полагаю, мне следует добавить, что есть несколько причин, по которым вы могли бы захотеть сделать что-то подобное.Например, если вам действительно нужно знать порядок, в котором Cat были добавлены в коллекцию, сохранение исходного порядка может иметь некоторый смысл.Аналогичным образом, если вы обычно используете коллекцию таким образом, чтобы извлекать выгоду из-за того, что они непрерывны в памяти, и только редко добавляет новый элемент, возможно, имеет смысл сохранитьоднако данные в vector, чем set.

A set, предназначены для выполнения точно того, что здесь делается, поэтому set является очевидным выбором(отсутствуют веские причины использовать vector, которые просто не видны на том, что вы показали).

2 голосов
/ 03 марта 2011

Добавляет элемент с именем morris к вектору cats ЕСЛИ у вектора его еще нет!

std::find используется для проверки, находится ли элемент morris в векторе cats или нет. Не имеет, std::find возвращаемое значение будет равно cats.end(). После этого все остальное в значительной степени прямо вперед.

1 голос
/ 03 марта 2011

Сначала будьте осторожны: ваш комментарий неверен.cats - это не вектор объектов Cat, а вектор указателей на объекты cat.

Теперь утверждение:

std :: find (cats.begin (), cats.end(), Моррис)

подразумевает, что у вас есть Кошка * где-то по имени Моррис.Этот оператор будет искать вектор между двумя предоставленными итераторами (то есть: cats.begin () и cats.end ()) для указателя на Cat, равный morris (тот же адрес).Если ничего не найдено, std :: find возвращает второй итератор, поэтому в вашем случае "cats.end ()"

Следовательно "if (std :: find (cats.begin (), cats.end)(), morris) == cats.end ()) {cats.push_back (morris);} "на обычном английском языке означает" если морриса еще нет в векторе кошек, поставьте его в конце "

Мне будет трудно быть более конкретным, если мы не будем точно знать, что вас беспокоит

1 голос
/ 03 марта 2011

cats - это вектор указателей на объекты Cat, а не вектор объектов Cat.

При этом поиск по всему диапазону кошек (от cats.begin () до cats.end ()) объекта (указателя на кошку) равен Моррису

std::find(cats.begin(), cats.end(), morris)

Возвращаемое значение представляет собой итератор в векторе, указывающий на объект, если он был найден, и возвращает конечный итератор (cats.end ()), если он не был найден. Имея это в виду, это:

if (std::find(cats.begin(), cats.end(), morris) == cats.end())

- это проверка, чтобы определить, содержит ли этот объект кошки (моррис). А если нет, то он выполняет это:

cats.push_back(morris);

, который помещает объект (моррис) в вектор.

1 голос
/ 03 марта 2011

Предполагая, что код правильный (например, тип и инициализация Морриса и использование указателей для сравнения), нужно посмотреть, есть ли Моррис в коллекции кошек, а если нет, добавить его к нему.

0 голосов
/ 03 марта 2011
std::vector<Cat*> cats; //I get that cats is a vector of Cat objects

Вы ошибаетесь. cats - это std::vector указателей на класс Cat. Есть разница: Cat s находятся в стеке, создаются с помощью

Cat morris;

и не должны быть удалены. Указатели, как в вашем примере, создаются

Cat* morris = new Cat();

и должен быть удален, как только закончите, прежде чем выбросить указатель:

delete morris;

Теперь я добавлю небольшой код к вашему примеру:

Cat* morris = new Cat();

if (std::find(cats.begin(), cats.end(), morris) == cats.end()) {
   cats.push_back(morris);
}

Создает динамически размещенный объект morris типа Cat в куче. Затем std::find используется для поиска вектора cats для вновь созданного объекта, который всегда будет терпеть неудачу в этом фрагменте кода. Если std::find терпит неудачу, он возвращает итератор к элементу после последнего элемента в контейнере (это именно то, что std::vector::end() возвращает). Поэтому, если morris не найден, код создаст новый элемент в конце вектора и добавит к нему morris.

...