Question

Here's what I'm trying to achieve:

#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';
    }
}

I'd like to use smart pointers instead of raw pointers, seeing as how they are much better, but can't really figure out how to implement switching back and forth (this is to be used for taking turns in a game; It's a Player *).

I tried replacing the pointers here with std::unique_ptr and std::shared_ptr in two separate tests, using reset to switch, with both giving random numbers after the first one, as expected.

Next, I tried with std::weak_ptr as it looks like what I need, although the interface isn't really that similar. From what I've seen, the only way to use it is through lock(), so I tried prepending lock(). to the calls of reset and appending it to dereferencing, but that crashed.

How can I use std::weak_ptr instead of a raw pointer, or can I actually use one of the other ones somehow?

Was it helpful?

Solution

Rather than using raw pointers for this type of indexing operation, I think you should look into using std::vector::iterator, keeping in mind that any insertion operation into a std::vector could invalidate the iterator. For instance, you could do the following:

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';
}

OTHER TIPS

Smart pointers are not "much better" by definition. They are only useful if they need to manage the memory they're pointing to.

As your pointers are simply pointing to elements in a vector, you don't want smart pointers at all. Most smart pointers will try to delete the memory they're pointing to when they go out of scope, which in this case will result in nasal demons.

Be aware, though, that resizing the vector may cause all your pointers to be invalidated. Ensure that you're not adding or removing elements while the pointers are still in scope.

In this case, players taking turns, I would probably not use pointers at all, but rather something like this:

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();
    }
}

Just realized you might mean you want a smart pointer to the int within a vector, not to change the ints in the vector to smart pointers. I wouldn't do that at all. I'd use the vector's iterators:

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

Using shared, unique, or any other pointer to the inside of your vector would result in bad, bad, bad things. Using raw pointers is not warranted either as they don't indicate anything about what they're pointing at. The vector's iterators on the other hand, although probably implemented as raw pointers, have clear, documented rules regarding their use which you can document in your code by using them.

Do not forget that "smart pointer" includes iterators.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top