Reputation: 3072
I want to use unique and shared_ptr to take care of allocated memory. But as far as I can see the access to the memory(get,...) is always const and return const pointer so I cannot manipulate the memory stored.
EXAMPLE:
std::unique_ptr<int[]> ptr( new int[42]);
memset(ptr.get(),0,42*sizeof(int)); //not possible ptr.get() returns const pointer
Is there a work around? If there is no way to manipulate the memory, what are the design reasons to not offer such an interface?
Upvotes: 2
Views: 1928
Reputation: 69882
Now that the mechanics of std::unique_ptr<>::get()
are understood, you may see some value in a more idiomatic algorithm-based approach.
Arguably it's more readable, avoids casts, will work should you change your mind about the underlying storage and is just as efficient.
some examples:
std::fill(ptr.get(), ptr.get() + 42, 0);
std::fill(&ptr[0], &ptr[42], 0);
std::fill(std::addressof(ptr[0]), std::addressof(ptr[42]), 0);
and with a little boilerplate:
for (auto& x : linear_range(ptr.get(), 42)) {
x = 0;
}
With optimisations enabled, all of these evaluate to the same efficient code.
boilerplate is here:
template<class I1, class I2>
struct range_impl {
auto begin() const { return i1; }
auto end() const { return i2; }
I1 i1;
I2 i2;
};
template<class I1, class I2>
auto range(I1 i1, I2 i2) {
return range_impl<I1, I2> { i1, i2 };
}
template<class I1>
auto linear_range(I1 i1, std::size_t length) {
return range(i1, std::next(i1, length));
}
Upvotes: 2
Reputation: 8284
The function signature for std::unique_ptr::get
is
the type of pointer
being "std::remove_reference<Deleter>::type::pointer
if that type exists, otherwise T*
"
The only const
in that signature being for the function itself, so that it can be called on a const std::unique_ptr<int> a;
So your premise of and return const pointer
is not true. You can change the memory pointed to by a smart pointer via a pointer retrieved from its get()
member function.
Additionally memset(ptr.get(),0,42*sizeof(int));
is also fine and doesn't need any casts because you can still implicitly convert any pointer to a void pointer according to this pointer-conversion rule:
A prvalue pointer to any (optionally cv-qualified) object type T can be converted to a prvalue pointer to (identically cv-qualified) void. The resulting pointer represents the same location in memory as the original pointer value. If the original pointer is a null pointer value, the result is a null pointer value of the destination type.
So, your code has no issues and seems to be compliant with the standard.
Upvotes: 4