如何修改std::shared_ptr(unique_ptr)保护的内存

how to change memory guarded by std::shared_ptr(unique_ptr)

本文关键字:ptr unique 保护 内存 何修改 修改 std shared      更新时间:2023-10-16

我想使用unique和shared_ptr来处理分配的内存。但据我所知,对内存的访问(get,…)总是const,并返回const指针,所以我不能操作存储的内存。

的例子:

std::unique_ptr<int[]> ptr( new int[42]);
memset(ptr.get(),0,42*sizeof(int)); //not possible ptr.get() returns const pointer

有解决办法吗?如果没有办法操作内存,那么不提供这样一个接口的设计原因是什么?

std::unique_ptr::get的函数签名为

pointer get() const;

如果pointer的类型存在,则该类型为"std::remove_reference<Deleter>::type::pointer",否则为"T*"

该签名中唯一的const是针对函数本身的,因此它可以在const std::unique_ptr<int> a;

上被调用

所以你的and return const pointer的前提是不正确的。您可以通过从其get()成员函数中检索指针来更改智能指针所指向的内存。

另外,memset(ptr.get(),0,42*sizeof(int));也很好,不需要任何类型转换,因为您仍然可以根据此指针转换规则隐式地将任何指针转换为void指针:

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.

所以,你的代码没有问题,似乎符合标准。

既然已经理解了std::unique_ptr<>::get()的机制,那么您可能会在更习惯的基于算法的方法中看到一些价值。

可以说,它更具可读性,避免了强制类型转换,如果你改变了对底层存储的想法,它也可以工作,而且同样高效。

一些例子:

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

和一个小样板:

for (auto& x : linear_range(ptr.get(), 42)) {
  x = 0;
}

启用优化后,所有这些都计算为相同的高效代码。

模板在这里:

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