2012-05-07 3 views
1

Вот что я пытаюсь достичь:Как это сделать с помощью 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 вместо необработанного указателя, или я могу каким-то образом использовать один из них?

+0

Здесь вам не нужен weak_ptr, так как нет цикла. Почему не работает shared_ptr? Я бы предложил разместить этот код, ошибку, которую вы получаете, и попросить о помощи там. unique_ptr не будет работать, потому что ... ну, только один может указать на одно и то же ... это * уникальный *. –

+0

@CrazyEddie, общий указатель не работает, потому что он единственный, указывающий на него, поэтому, когда он переключается на другого игрока, ничто не указывает на первое. – chris

ответ

4

Вместо использования необработанных указателей для этого типа операции индексирования, я думаю, вы должны изучить использование 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'; 
} 
+0

Это удаление было случайно: p Как использовать итератор для этого? – chris

+0

Хотя у других есть хорошие моменты, мне нравится это лучше всего. Благодарю. – chris

4

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

Как ваши указатели просто указывают на элементы в 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(); 
    } 
} 
+0

Я вижу, я неправильно понял их использование. Я действительно помню, что читал что-то, чтобы просто использовать обычный указатель, просто указывая на что-то немного назад. Тем не менее, у меня есть классный класс, поэтому я немного уйду. – chris

+0

@chris: Смотрите [этот вопрос] (http://stackoverflow.com/questions/8706192/which-kind-of-pointer-do-i-use-when). – Xeo

+0

@Xeo, очень информативный, спасибо. Я никогда не обнаружил этого при поиске. – chris

0

Просто понял, что вы, возможно, означает, что вы хотите смарт-указатель на INT в пределах вектор, чтобы не изменять ints в векторе на интеллектуальные указатели. Я бы этого не сделал. Я хотел бы использовать итераторы вектора в:

for (int i = 0; i < 10; ++i) { 
    auto it = it.begin() + (i % 2 ? 1:0); 
    f(*it); 
} 

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

Не забывайте, что «умный указатель» включает итераторы.

Смежные вопросы