How do I increment a shared pointer?

Started by
5 comments, last by ChaosEngine 10 years, 2 months ago

shared_ptr<PxVec3> vertices = shared_ptr<PxVec3>(new PxVec3[data->points->size()],
[](PxVec3* p){delete[] p; });

turns out I can't use vertices[5],neither can I use vertices++

How am I supposed to access any other element in the array?

Advertisement

That's not possible.

What are you trying to accomplish?

Why don't you use a std::vector instead of a plain array? i.e a shared_ptr to a std::vector

I'm trying to get the same behaviour as int *i = new int[30]; so I can do i[5] = 10.

I revised the code,but it still doesn't work:

shared_ptr<PxVec3> vertices(new PxVec3[data->points->size()],
[](PxVec3* p){delete[] p; });

Well, there's shared_ptr::get which returns the underlying raw pointer.

So I guess you could do (didn't test this): i.get()[5] = 10;

But I suggest you don't use shared_ptr-to-array.

C++17 may add N3869 and N3870 ("Extending make_shared to Support Arrays" and "Extending make_shared to Support Arrays", respectively) but currently what you're asking for is not supported without hacks or building your own smart pointer.

It is illegal to try to shove an array into a shared_ptr even if you manage to contort it without _also_ adding a custom deleter. Otherwise your array allocated with array operator new[] would be free with the scalar operator delete, which is quite bad.

Nothing stops you from making a std::shared_ptr to a std::array or std::vector, aside from the experience that would stop you from using std::shared_ptr in the first place. shared_ptr is the lazy way out of thinking through what you're actually doing and too easily just causes all sorts of other hard-to-debug problems.

Use a unique_ptr which already supports arrays:

std::unique_ptr<int[]> array{new int[N]};
Beware the exception safety problems here; wrap this up in a custom template (make_unique is missing until C++14 and I'm unsure if make_unique supports arrays):

// default initialize
template <typename T>
auto make_unique_array(size_t N) -> std::unique_ptr<T[]>
{
  return {new T[N]};
}

// initialize to value
template <typename T>
auto make_unique_array(size_t N, const T& value) -> std::unique_ptr<T[]>
{
  auto ptr = std::unique_ptr<T[]>{new T[N]};
  for (size_t i = 0; i != N; ++i)
    ptr[i] = value;
  return ptr;
}

// initialize with range and allocate with ranged-size left as exercise to reader

Sean Middleditch – Game Systems Engineer – Join my team!

I have no idea if unique_ptr does what you need, so I'll just answer your actual question. If you need shared_ptr, you use get()[5] syntax. You can also override operator [] so you can use i[5] syntax. Quick example:


class shared_ptr_int_array : public shared_ptr<int>{
public:
  shared_ptr_int_array(int* p) : shared_ptr<int>(p) {}
  int& operator[](ptrdiff_t i){ return *(get() + i); }
};

int main(){
  shared_ptr_int_array i(new int[50]);
  i[5] = 10;
  return 0;
}

I didn't specify the destructor, so make sure you use delete[] instead of delete. You already knew that in your original post, but I guess it's obligatory to mention it.

Let's take a step back.

Ask yourself what you are trying to achieve with this. What are the ownership semantics of vertices? What is the scope of the variable and it's expected lifetime?

Once you have answered those questions, you can then make an educated decision on which container to use.

But based solely on your code snippet, I'd agree with madhed and say you most likely want a vector.

if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight

This topic is closed to new replies.

Advertisement