Как я могу сделать это с помощью Smart Pointers?
Вот чего я пытаюсь достичь:
#include <iostream>
using std::cout;
#include <vector>
using std::vector;
int main()
{
vector<int> a {3, 7};
int *p = &a.at (0); //assign 3
for (int i = 0; i < 10; ++i) //swap and print (3,7,3...)
{
p = (*p == a.at (0) ? &a.at (1) : &a.at (0));
cout << *p << '\n';
}
}
Я бы хотел использовать умные указатели вместо сырых указателей, видя, что они намного лучше, но не могу понять, как реализовать переключение вперед и назад (это нужно использовать для смены хода в игре; это Player *
).
Я попытался заменить указатели здесь std::unique_ptr
а также std::shared_ptr
в двух отдельных тестах, используя reset
переключаться, причем оба дают случайные числа после первого, как и ожидалось.
Далее я попробовал с std::weak_ptr
как это выглядит, что мне нужно, хотя интерфейс не так уж похож. Из того, что я видел, единственный способ использовать это через lock()
поэтому я попытался предугадать lock().
на вызовы reset
и добавив его к разыменованию, но это потерпело крах.
Как я могу использовать std::weak_ptr
вместо необработанного указателя, или я могу как-то использовать один из других?
3 ответа
Вместо того, чтобы использовать необработанные указатели для этого типа операции индексирования, я думаю, что вы должны изучить использование std::vector::iterator
имея в виду, что любая операция вставки в std::vector
может сделать недействительным итератор. Например, вы можете сделать следующее:
typedef std::vector<int>::iterator iter_t;
vector<int> a {3, 7};
iter_t p = iter_t(&a.at(0)); //assign 3
for (int i = 0; i < 10; ++i) //swap and print (3,7,3...)
{
p = (*p == a.at(0) ? iter_t(&a.at(1)) : iter_t(&a.at(0)));
cout << *p << '\n';
}
Умные указатели не намного лучше по определению. Они полезны, только если им нужно управлять памятью, на которую они указывают.
Поскольку ваши указатели просто указывают на элементы в vector
Вам не нужны умные указатели вообще. Большинство умных указателей будут пытаться удалить память, на которую они указывают, когда они выходят за рамки видимости, что в этом случае приведет к появлению носовых демонов.
Имейте в виду, однако, что изменение размера вектора может привести к тому, что все ваши указатели станут недействительными. Убедитесь, что вы не добавляете и не удаляете элементы, пока указатели находятся в области видимости.
В этом случае, если игроки ходят по очереди, я бы, вероятно, вообще не использовал указатели, а что-то вроде этого:
int main()
{
vector<int> players {3, 7};
int current_player = 0;
while (!game_over())
{
cout << players[current_player] << '\n';
current_player = (current_player + 1) % players.size();
}
}
Просто понял, что вы можете иметь в виду, что вы хотите иметь умный указатель на int внутри вектора, а не менять целые числа в векторе на умные указатели. Я бы не стал этого делать. Я бы использовал итераторы вектора:
for (int i = 0; i < 10; ++i) {
auto it = it.begin() + (i % 2 ? 1:0);
f(*it);
}
Использование общего, уникального или любого другого указателя внутри вашего вектора приведет к плохим, плохим и плохим вещам. Использование необработанных указателей также не гарантируется, так как они ничего не указывают на то, на что они указывают. С другой стороны, итераторы вектора, хотя, возможно, и реализованы в виде необработанных указателей, имеют четкие, документированные правила их использования, которые вы можете документировать в своем коде, используя их.
Не забывайте, что "умный указатель" включает в себя итераторы.