我想使用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
有解决方法吗?如果没有办法操纵内存,那么没有提供这种界面的设计理由是什么?
答案 0 :(得分:3)
std::unique_ptr::get
的功能签名是
pointer
的类型&#34; std::remove_reference<Deleter>::type::pointer
如果该类型存在,否则T*
&#34;
该签名中唯一const
用于函数本身,因此可以在const std::unique_ptr<int> a;
上调用
所以and return const pointer
的前提是不正确的。您可以通过从其get()
成员函数检索的指针更改智能指针指向的内存。
另外memset(ptr.get(),0,42*sizeof(int));
也很好,并且不需要任何强制转换,因为您仍然可以根据this pointer-conversion rule隐式地将任何指针转换为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.
因此,您的代码没有问题,似乎符合标准。
答案 1 :(得分:2)
现在已经理解了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));
}