Должен повысить:: ptr_vector использоваться на месте станд.:: вектор все время?

Согласно просьбе в исходной версии вопроса, и согласно редактированиям, сделанным OP, мы создаем список увеличения последовательностей, затем вычисляем различия между макс. и минута каждого из них:

def spans(data):
    sequences = [[data[0]]]

    for val in data[1:]:
        if val >= sequences[-1][-1]:
            sequences[-1].append(val)
        else:
            sequences.append([val])

    return [s[-1] -s[0] for s in sequences]

Образец, выполненный с данными OP:

data = [0, 10, 20, 5, 10, 30, 20, 35]
print(spans(data))
# [20, 25, 15]

Другой:

print(spans([2, 4, 6, 8, 9, 4, 5, -2, -1, 5, 4]))
# [7, 1, 7, 0]
6
задан jgrowl 3 September 2009 в 17:46
поделиться

8 ответов

Вы должны использовать только собственные интеллектуальные указатели и контейнеры указателей где есть четкая передача права собственности. Не имеет значения, является ли объект временным или нет - все, что имеет значение, имеет ли он право собственности или нет (и, следовательно, отказывается ли предыдущий владелец от владения).

Если вы создаете временный вектор указателей, просто для передачи это к какой-то другой функции, а исходный ptr_vector по-прежнему ссылается на все эти объекты, нет передачи права собственности, и поэтому вы должны использовать простой вектор для временного объекта - так же, как и вы использовать необработанный указатель для передачи одного объекта из ptr_vector в функцию, которая принимает указатель,

15
ответ дан 8 December 2019 в 03:27
поделиться

Most likely, the solution you're looking for is

std::vector<Tile>

There's no need for pointers most of the time. The vector already takes care of memory managements of the contained objects. The tiles are owned by the game, aren't they? The way to make that explicit is to put the objects themselves in the game class -- the only cases where you typically need pointers and dynamically allocated individual objects is if you need 1) polymorphism, or 2) shared ownership.

But pointers should be the exception, not the rule.

5
ответ дан 8 December 2019 в 03:27
поделиться

boost :: ptr_vector служит только для улучшения семантики использования векторов указателей. Если в вашем примере исходный массив может быть уничтожен, пока используется временный набор векторов, то вам определенно следует использовать вектор shared_ptr s, чтобы предотвратить их удаление во время использования. Если нет, то может подойти простой старый вектор указателей. Неважно, выберете ли вы std :: vector или boost :: ptr_vector , за исключением того, насколько красиво выглядит код, использующий вектор.

1
ответ дан 8 December 2019 в 03:27
поделиться

Если тайлы принадлежат игре, то за них отвечает Игра.

Похоже, что мешок никогда не владеет объектами, поэтому он не должен отвечать за их удаление. Таким образом, я бы использовал ptr_vector внутри объекта Game. Но используйте std :: vector в сумке.

Примечание: я бы никогда не позволил никому, использующему сумку, извлекать указатель на плитку из сумки. Они должны иметь возможность извлекать только ссылку на плитку из пакета.

1
ответ дан 8 December 2019 в 03:27
поделиться

По моему опыту, можно выделить три основных формы собственности. Я буду называть их деревом, DAG и графом.

Самым распространенным является дерево. Родитель владеет своими дочерними элементами, а тот, в свою очередь, владеет своими детьми и так далее. auto_ptr, scoped_ptr, голые указатели и классы boost ptr_x - это то, что вы обычно видите здесь. На мой взгляд, голых указателей следует избегать, поскольку они вообще не передают семантику владения.

Второй по распространенности - DAG. Это означает, что у вас может быть совместное владение. Дети, которыми владеет родитель, также могут быть детьми других детей, которыми владеет родитель. Здесь главным действующим лицом является шаблон TR1 и boost shared_ptr. Подсчет ссылок - жизнеспособная стратегия, когда у вас нет циклов.

Третьим наиболее распространенным является полный граф. Это означает, что у вас могут быть циклы. Есть несколько стратегий для того, чтобы разорвать эти циклы и вернуться к DAG за счет некоторых возможных источников ошибок. Обычно они представлены шаблоном weak_ptr TR1 или boost.

Полный граф, который нельзя разбить на DAG с помощью weak_ptr, - это проблема, которую нелегко решить в C ++. Единственные хорошие обработчики - это схемы сборки мусора. Они также являются наиболее общими и способны неплохо справляться с двумя другими схемами. Но их универсальность имеет свою цену.

На мой взгляд, вы не можете злоупотреблять классами контейнеров ptr_x или auto_ptr, если вам действительно не нужно использовать контейнеры объектов вместо контейнеров указателей. shared_ptr можно использовать слишком часто. Хорошо подумайте, действительно ли вам нужен DAG.

Конечно, я думаю, что людям следует просто использовать контейнеры scope_ptrs вместо классов boost ptr_x, но для этого придется подождать C ++ 0x. : - (

6
ответ дан 8 December 2019 в 03:27
поделиться

В вашем В примере с игровыми плитками, я первым делом хотел создать vector , а не vector или ptr_vector. Затем используйте указатели на плитки по своему усмотрению, не беспокоясь о праве собственности, при условии, что объекты, которые содержат указатели, не переживают вектор плиток. Вы сказали, что он уничтожается только по окончании игры, так что это не должно вызывать затруднений.

Конечно, могут быть причины, по которым это невозможно, например, потому что Tile является полиморфным базовым классом, а сами плитки не являются все одного класса. Но это C ++, а не Java, и не для каждой задачи всегда нужен динамический полиморфизм. Но даже если вам действительно нужны указатели, вы все равно можете делать копии этих указателей без какой-либо семантики владения, при условии, что объем и продолжительность хранения указанных объектов понимаются шире, чем объем и продолжительность использования указателя:

int main() {
    vector<Tile*> v;
    // fill in v, perhaps with heap objects, perhaps with stack objects.
    runGame(v);
}

void runGame(const vector<Tile*> &v) {
    Tile *firsttile = v[0];
    vector<Tile*> eventiles;
    eventiles.push_back(v[2]);
    eventiles.push_back(v[4]);
    // and so on. No need to worry about ownership, 
    // just as long as I don't keep any pointers beyond return.
    // It's my caller's problem to track and free heap objects, if any.
}
1
ответ дан 8 December 2019 в 03:27
поделиться

Если тайлы помещены в сумку и кто-то украдет сумку, вы потеряете все плитки. Поэтому плитки, хотя и временно, но они принадлежат Сумке на короткое время. Я полагаю, вам следует передать право собственности здесь.

Но лучше не связываться с правом собственности, потому что я не понимаю, зачем это нужно в данном конкретном случае. Если что-то есть за кадром, продолжайте, делайте свой выбор.

0
ответ дан 8 December 2019 в 03:27
поделиться

Я согласен с использованием вектора вместо прыжков прямо в выделенный кучей T - это хороший инстинкт, но я легко вижу, что Tile является типом, в то время как построение копии является дорогостоящим, что может помешать практической стратегии роста вектора. Конечно,

0
ответ дан 8 December 2019 в 03:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: